Du liest:
Alles was du über das runden in Python wissen musst

Alles was du über das runden in Python wissen musst

von Patrick
20.04.2020
Jetzt Python programmieren lernen

Oft ist es einfacher, mit kürzeren Zahlen zu rechnen, als mit endlos langen wie π/Pi. Für das Runden von Zahlen oder auch eigenen Klassen stellt Python viele Möglichkeiten bereit, von denen ich dir im Folgenden ein paar vorstellen möchte.

1. Runden mit Python

Mit der Funktion int(Zahl) kannst du nur den Typ der Variablen ändern, Dezimalstellen werden dabei komplett abgeschnitten.

zahl = 7.895
print(zahl)
print(int(zahl))

Output

7.895
7

Um eine Zahl wirklich zu Runden, stehen uns die hier dargestellten Methoden zur Verfügung.

1.1 Die Python round Funktion

Am einfachsten kannst du Zahlen in Python runden, indem du die eingebaute Funktion round verwendest.

round(Zahl, Dezimalstellen)
    Zahl (Erforderlich)             Die Zahl, die gerundet werden soll.
    Dezimalstellen (Optional)       Anzahl der Dezimalstellen welche zum Runden 									genutzt werden sollen. Standart ist 0

So können wir zum Beispiel das in der Einleitung erwähnte  π/Pi runden.

from math import pi
print(round(pi, 2), f"= round({pi}, 2)")
print(round(pi, 3), f"= round({pi}, 3)")
print(round(pi, 10), f"= round({pi}, 10)")

Output:

3.14 = round(3.141592653589793, 2)
3.142 = round(3.141592653589793, 3)
3.1415926536 = round(3.141592653589793, 10)

Im vorigen Beispiel scheint nichts auffällig anders zu sein, jedoch im Nächsten könnten die Ergebnisse vielleicht etwas unerwartet ausfallen.

zahlen = [2.695, 2.685, 2.675, 2.665, 2.655, 2.645, 2.635, 2.625, 2.615, 2.605]
for zahl in zahlen:
    print(round(zahl, 2), f"= round({zahl}, 2)")

Output:

2.69 = round(2.695, 2)
2.69 = round(2.685, 2)
2.67 = round(2.675, 2)
2.67 = round(2.665, 2)
2.65 = round(2.655, 2)
2.65 = round(2.645, 2)
2.63 = round(2.635, 2)
2.62 = round(2.625, 2)
2.62 = round(2.615, 2)
2.6 = round(2.605, 2)

Hier fällt auf, dass fast alle Ergebnisse auf einer ungeraden Zahl enden, bis auf die letzten Drei, wobei es sich nicht etwa um einen Fehler handelt, sondern um die Implementierte Methode für das “Banker’s rounding” in Python 3 (siehe auch https://bugs.python.org/issue36082).

1.2 Auf-/Abrunden mit math.ceil()/floor()

Das Modul math verfügt über einige praktische Funktionen, von denen ich ceil und floor kurz vorstelle.

import math
math.ceil(3.141592653589793)
# 4
math.ceil(2.605)
# 3
math.ceil(2.665)
# 3
math.ceil(2.3333333)
# 3

Mit math.ceil lässt sich der nächsthöhere ganzzahlige Wert einer Zahl ermitteln, mit math.floor lässt sich der abgerundete Wert ebenso einfach errechnen.

math.floor(3.141592653589793)
# 3
math.floor(2.605)
# 2
math.floor(2.665)
# 2
math.floor(2.3333333)
# 2

1.3 Python round() mit eigenen Klassen unterstützen

Du kannst, um round für deine eigenen Klassen zu unterstützen, die magic method __round__ implementieren, wie hier veranschaulicht:

class Data(object):
    def __init__(self, zahl):
        self.zahl = zahl

    def __round__(self, dezimalstellenanzahl):
        return round(self.zahl, dezimalstellenanzahl)

zahlen = [2.695, 2.685, 2.675, 2.665, 2.655, 2.645, 2.635, 2.625, 2.615, 2.605]
for zahl in zahlen:
    d = Data(zahl)
    print(round(d, 2))

Output:

2.69
2.69
2.67
2.67
2.65
2.65
2.63
2.62
2.62
2.6

Wenn du möchtest, kannst du an dieser Stelle auch deinen eigenen Rundungsalgorithmus implementieren. Und das geht dann mit “Round half up”.

import math
zahlen = [2.696, 2.695, 2.694, 2.685, 2.675, 2.665, 2.655, 2.645, 2.635, 2.625, 2.615, 2.605]
class Data(object):
    def __init__(self, i):
        self.zahl = i

    def __round__(self, dezimalstellen):
        # round_half_up
        multiplikator = 10 ** dezimalstellen
        return math.floor(self.zahl * multiplikator + 0.5) / multiplikator

for zahl in zahlen:
    d = Data(zahl)
    print(round(d, 2), f"= round({d.zahl}, 2)")

Output:

2.7 = round(2.696, 2)
2.7 = round(2.695, 2)
2.69 = round(2.694, 2)
2.69 = round(2.685, 2)
2.68 = round(2.675, 2)
2.67 = round(2.665, 2)
2.66 = round(2.655, 2)
2.65 = round(2.645, 2)
2.64 = round(2.635, 2)
2.63 = round(2.625, 2)
2.62 = round(2.615, 2)
2.61 = round(2.605, 2)

2. Was ist Decimal in Python?

Decimal ist eine Klasse in Python, welche Gleitkommazahlen darstellen kann und eine hohe Rechengenauigkeit erlaubt.

2.1 Konvertierung von float zu Decimal

Durch die Implementierung von float kann es unter Umständen zu Rechenungenauigkeiten kommen, wie man diese umgehen kann mittels Konvertierung in string zeigt das folgende Beispiel.
(siehe auch Blogpost int zu string, Sektion eigene Klasse mit __str__()-Unterstützung)

from decimal import Decimal
zahlen = [2.696, 2.695, 2.694, 2.685, 2.675, 2.665, 2.655, 2.645, 2.635, 2.625, 2.615, 2.605]
for zahl in zahlen:
    d = Decimal(zahl)
    print(d, "float")
    d = Decimal(str(zahl))
    print(d, "string")

Output:

2.696000000000000174082970261224545538425445556640625 float
2.696 string
2.694999999999999840127884453977458178997039794921875 float
2.695 string
2.69399999999999995026200849679298698902130126953125 float
2.694 string
2.685000000000000053290705182007513940334320068359375 float
2.685 string
2.67499999999999982236431605997495353221893310546875 float
2.675 string
2.66500000000000003552713678800500929355621337890625 float
2.665 string
2.654999999999999804600747665972448885440826416015625 float
2.655 string
2.645000000000000017763568394002504646778106689453125 float
2.645 string
2.6349999999999997868371792719699442386627197265625 float
2.635 string
2.625 float
2.625 string
2.6150000000000002131628207280300557613372802734375 float
2.615 string
2.604999999999999982236431605997495353221893310546875 float
2.605 string

2.2  Weitere Rundungsmethoden mit Decimal

Der gleiche Effekt wie in unserer selbst erstellten Klasse kann auch mit einigen der Rundungsmethoden von Decimal erzielt werden.

Das Modul decimal stellt folgende Rundungsmethoden zur Verfügung:
ROUND_05UP
ROUND_DOWN
ROUND_HALF_DOWN
ROUND_UP
ROUND_HALF_UP
ROUND_CEILING
ROUND_FLOOR
ROUND_HALF_EVEN

Wie man diese verschiedenen Varianten zu runden nun auf Zahlen anwendet, zeigt das folgende Beispiel, wobei der Output manuell von mir in einer Tabelle strukturiert wurde um eine bessere Übersicht über die Ergebnisse zu gewährleisten.

from decimal import Decimal, ROUND_05UP, ROUND_DOWN, ROUND_HALF_DOWN, ROUND_UP, ROUND_HALF_UP, ROUND_CEILING, ROUND_FLOOR, ROUND_HALF_EVEN
zahlen = [2.696, 2.695, 2.694, 2.685, 2.625, 2.615, 2.605]
for zahl in zahlen:
    d = Decimal(str(zahl))
    print(d)
    print(d.quantize(Decimal('1.00'), rounding=ROUND_05UP), "ROUND_05UP")
    print(d.quantize(Decimal('1.00'), rounding=ROUND_DOWN), "ROUND_DOWN")
    print(d.quantize(Decimal('1.00'), rounding=ROUND_HALF_DOWN), "ROUND_HALF_DOWN")
    print(d.quantize(Decimal('1.00'), rounding=ROUND_UP), "ROUND_UP")
    print(d.quantize(Decimal('1.00'), rounding=ROUND_HALF_UP), "ROUND_HALF_UP")
    print(d.quantize(Decimal('1.00'), rounding=ROUND_CEILING), "ROUND_CEILING")
    print(d.quantize(Decimal('1.00'), rounding=ROUND_FLOOR), "ROUND_FLOOR")
    print(d.quantize(Decimal('1.00'), rounding=ROUND_HALF_EVEN), "ROUND_HALF_EVEN")
 2.6962.6952.6942.6852.6252.6152.605
ROUND_05UP2.692.692.692.682.622.612.61
ROUND_DOWN2.692.692.692.682.622.612.60
ROUND_HALF_DOWN2.702.692.692.682.622.612.60
ROUND_UP2.702.702.702.692.632.622.61
ROUND_HALF_UP2.702.702.692.692.632.622.61
ROUND_CEILING2.702.702.702.692.632.622.61
ROUND_FLOOR2.692.692.692.682.622.612.60
ROUND_HALF_EVEN2.702.702.692.682.622.622.60
Outputs der Rundungsmethoden

3. Fazit

Das Runden mit der eingebauten Python round Funktion scheint bei erster Betrachtung etwas merkwürdig, jedoch können mit dem Datentypen Decimal noch weitere Rundungsmethoden verwendet werden. Ebenso kannst du mit der magic method __round__ einfach selbst ein Verhalten für deine Objekte festlegen, wenn round auf sie angewendet wird.

Hat dir dieser Beitrag gefallen? Hast du noch Fragen? Bitte schreibe es in die Kommentare!



Bislang gibt es keine Kommentare. Markier dein Revier und sei der Erste!

Schreibe einen Kommentar

Das könnte dich auch interessieren