So runden Sie Zahlen in Python

So runden Sie Zahlen in Python

Es ist die Ära der Big Data, und jeden Tag versuchen immer mehr Unternehmen, ihre Daten zu nutzen, um fundierte Entscheidungen zu treffen. Viele Unternehmen wenden sich zur Analyse ihrer Daten dem leistungsstarken Data Science-Ökosystem von Python zu, wie aus https://stackoverflow.blog/2017/09/14/python-growing-quickly/[Pythons zunehmender Beliebtheit im Bereich Data Science hervorgeht.

Eine Sache, die jeder Data Science-Praktiker beachten muss, ist, wie ein Datensatz voreingenommen sein kann. Schlussfolgerungen aus voreingenommenen Daten zu ziehen, kann zu kostspieligen Fehlern führen.

Es gibt viele Möglichkeiten, wie sich Verzerrungen in einen Datensatz einschleichen können. Wenn Sie einige Statistiken studiert haben, sind Sie wahrscheinlich mit Begriffen wie Berichtsverzerrung, Auswahlverzerrung und Stichprobenverzerrung vertraut. Es gibt eine andere Art von Verzerrung, die beim Umgang mit numerischen Daten eine wichtige Rolle spielt: die Rundungsverzerrung.

In diesem Artikel erfahren Sie:

  • Warum es wichtig ist, wie Sie Zahlen runden

  • Wie man eine Zahl nach verschiedenen Rundungsstrategien rundet und wie man jede Methode in reinem Python implementiert

  • Wie sich Rundungen auf Daten auswirken und welche Rundungsstrategie diesen Effekt minimiert

  • So runden Sie Zahlen in NumPy-Arrays und Pandas DataFrames

  • Wann sollten verschiedene Rundungsstrategien angewendet werden?

    *__ Nehmen Sie am Quiz teil:* Testen Sie Ihr Wissen mit unserem interaktiven Quiz „Runden von Zahlen in Python“. Nach Abschluss erhalten Sie eine Punktzahl, mit der Sie Ihren Lernfortschritt im Laufe der Zeit verfolgen können:

Dieser Artikel ist keine Abhandlung über die numerische Präzision beim Rechnen, obwohl wir kurz auf das Thema eingehen werden. Es ist nur eine Vertrautheit mit den Grundlagen von Python erforderlich, und die Mathematik, um die es hier geht, sollte sich für jeden wohl fühlen, der mit dem Äquivalent der High-School-Algebra vertraut ist.

Betrachten wir zunächst den in Python integrierten Rundungsmechanismus.

Pythons integrierte + round () + Funktion

Python verfügt über eine integrierte Funktion "+ round () ", die zwei numerische Argumente " n " und " ndigits " verwendet und die auf " ndigits " gerundete Zahl " n " zurückgibt. Das Argument " ndigits " ist standardmäßig Null. Wenn Sie es also weglassen, wird die Zahl auf eine Ganzzahl gerundet. Wie Sie sehen werden, funktioniert ` round () +` möglicherweise nicht ganz so, wie Sie es erwarten.

Die Art und Weise, wie die meisten Menschen lernen, eine Zahl zu runden, sieht ungefähr so ​​aus:

_ _ Runden Sie die Zahl + n + auf + p + Dezimalstellen, indem Sie zuerst den Dezimalpunkt in + n + um` + p + Stellen verschieben, indem Sie + n + mit 10ᵖ multiplizieren (10 erhöht auf die + p + te Potenz ) um eine neue Nummer + m + zu erhalten.

Schauen Sie sich dann die Ziffer "+ d " an der ersten Dezimalstelle von " m " an. Wenn " d " kleiner als 5 ist, runden Sie " m " auf die nächste ganze Zahl ab. Andernfalls runden Sie ` m +` auf.

Verschieben Sie schließlich den Dezimalpunkt um + p + Stellen zurück, indem Sie + m + durch 10 teilen. _ _

Es ist ein unkomplizierter Algorithmus! Zum Beispiel ist die auf die nächste ganze Zahl gerundete Zahl "+ 2,5 " " 3 ". Die auf eine Dezimalstelle gerundete Zahl " 1,64 " ist " 1,6 +".

Öffnen Sie nun eine Dolmetschersitzung und runden Sie "+ 2.5 " mit Pythons integriertem https://docs.python.org/3/library/functions.html#round [` round () +` auf die nächste ganze Zahl ] Funktion:

>>>

>>> round(2.5)
2

Keuchen!

Wie geht + round () + mit der Zahl + 1.5 + um?

>>>

>>> round(1.5)
2

Also, + + Runde () + Runden + 1,5 + bis + 2 + und + 2,5 + bis + 2 +!

Bevor Sie ein Problem mit dem Python-Bug-Tracker ansprechen, möchte ich Ihnen versichern, dass + round (2.5) + + 2 + zurückgeben soll. Es gibt einen guten Grund, warum sich + round () + so verhält wie es ist.

In diesem Artikel erfahren Sie, dass es mehr Möglichkeiten gibt, eine Zahl zu runden, als Sie vielleicht erwarten, mit jeweils einzigartigen Vor- und Nachteilen. + round () + verhält sich entsprechend einer bestimmten Rundungsstrategie - die möglicherweise diejenige ist, die Sie für eine bestimmte Situation benötigen oder nicht.

Sie fragen sich vielleicht: "Kann die Art und Weise, wie ich Zahlen runde, wirklich so viel Einfluss haben?" Schauen wir uns an, wie extrem die Rundungseffekte sein können.

Wie viel Einfluss kann Rundung haben?

Angenommen, Sie haben einen unglaublich glücklichen Tag und finden 100 Dollar vor Ort. Anstatt Ihr gesamtes Geld auf einmal auszugeben, entscheiden Sie sich dafür, klug zu spielen und Ihr Geld zu investieren, indem Sie einige Aktien verschiedener Aktien kaufen.

Der Wert einer Aktie hängt von Angebot und Nachfrage ab. Je mehr Leute eine Aktie kaufen möchten, desto mehr Wert hat diese Aktie und umgekehrt. An hochvolumigen Aktienmärkten kann der Wert einer bestimmten Aktie von Sekunde zu Sekunde schwanken.

Lassen Sie uns ein kleines Experiment durchführen. Wir geben vor, dass der Gesamtwert der von Ihnen gekauften Aktien jede Sekunde um eine kleine Zufallszahl schwankt, beispielsweise zwischen 0,05 und - 0,05 US-Dollar. Diese Schwankung muss nicht unbedingt ein schöner Wert mit nur zwei Dezimalstellen sein. Beispielsweise kann sich der Gesamtwert in einer Sekunde um 0,031286 USD erhöhen und in der nächsten Sekunde um 0,028476 USD verringern.

Sie möchten Ihren Wert nicht bis zur fünften oder sechsten Dezimalstelle verfolgen, also beschließen Sie, alles nach der dritten Dezimalstelle abzuschneiden. Im Rundungsjargon wird dies als Abschneiden der Zahl auf die dritte Dezimalstelle bezeichnet. Hier ist ein Fehler zu erwarten, aber wenn drei Dezimalstellen beibehalten werden, kann dieser Fehler nicht wesentlich sein. Richtig?

Um unser Experiment mit Python auszuführen, schreiben wir zunächst eine Funktion + truncate () +, die eine Zahl auf drei Dezimalstellen abschneidet:

>>>

>>> def truncate(n):
...     return int(n * 1000)/1000

Die Funktion + truncate () + verschiebt zuerst den Dezimalpunkt in der Zahl + n + drei Stellen nach rechts, indem + n + mit` + 1000 + multipliziert wird. Der ganzzahlige Teil dieser neuen Zahl wird mit `+ int () + genommen. Schließlich wird der Dezimalpunkt um drei Stellen nach links verschoben, indem "+ n " durch " 1000 +" geteilt wird.

Als nächstes definieren wir die Anfangsparameter der Simulation. Sie benötigen zwei Variablen: eine, um den tatsächlichen Wert Ihrer Bestände nach Abschluss der Simulation zu verfolgen, und eine für den Wert Ihrer Bestände, nachdem Sie bei jedem Schritt auf drei Dezimalstellen gekürzt haben.

Beginnen Sie mit der Initialisierung dieser Variablen auf + 100 +:

>>>

>>> actual_value, truncated_value = 100, 100

Lassen Sie uns nun die Simulation für 1.000.000 Sekunden (ca. 11,5 Tage) ausführen. Generieren Sie für jede Sekunde einen Zufallswert zwischen "+ -0,05 " und " 0,05 " mit der Funktion " uniform () " im Modul " random " und aktualisieren Sie dann " actual " und " abgeschnitten +" `:

>>>

>>> import random
>>> random.seed(100)

>>> for _ in range(1000000):
...     randn = random.uniform(-0.05, 0.05)
...     actual_value = actual_value + randn
...     truncated_value = truncate(truncated_value + randn)
...

>>> actual_value
96.45273913513529

>>> truncated_value
0.239

Das Fleisch der Simulation findet in der "+ for " - Schleife statt, die den " Bereich (1000000) " von Zahlen zwischen " 0 " und " 999.999 " durchläuft. Der Wert, der bei jedem Schritt aus " range () " entnommen wird, wird in der Variablen " _ +" gespeichert, die wir hier verwenden, da wir diesen Wert innerhalb der Schleife nicht benötigen.

Bei jedem Schritt der Schleife wird mit + random.randn () + eine neue Zufallszahl zwischen + -0.05 + und + 0.05 + generiert und der Variablen + randn + zugewiesen. Der neue Wert Ihrer Investition wird berechnet, indem Sie "+ randn " zu " actual_value " hinzufügen, und die abgeschnittene Summe wird berechnet, indem Sie " randn " zu " truncated_value " addieren und diesen Wert dann mit " truncate () +" abschneiden .

Wie Sie sehen können, indem Sie die Variable + actual_value + nach dem Ausführen der Schleife untersuchen, haben Sie nur etwa 3,55 USD verloren. Wenn Sie sich jedoch "+ abgeschnittener Wert +" angesehen hätten, hätten Sie gedacht, dass Sie fast Ihr gesamtes Geld verloren hätten!

*Hinweis:* Im obigen Beispiel wird die Funktion `+ random.seed () +` verwendet, um den Pseudozufallszahlengenerator zu setzen, damit Sie die hier gezeigte Ausgabe reproduzieren können.

Weitere Informationen zur Zufälligkeit in Python finden Sie unter https://realpython.com/python-random/[Generating Random Data in Python (Handbuch) von Real Python.

Wenn Sie für den Moment ignorieren, dass sich "+ round () " nicht ganz so verhält, wie Sie es erwarten, versuchen wir, die Simulation erneut auszuführen. Dieses Mal verwenden wir " round () ", um bei jedem Schritt auf drei Dezimalstellen zu runden, und " seed () +" die Simulation erneut, um die gleichen Ergebnisse wie zuvor zu erhalten:

>>>

>>> random.seed(100)
>>> actual_value, rounded_value = 100, 100

>>> for _ in range(1000000):
...     randn = random.uniform(-0.05, 0.05)
...     actual_value = actual_value + randn
...     rounded_value = round(rounded_value + randn, 3)
...

>>> actual_value
96.45273913513529

>>> rounded_value
96.258

Was für ein Unterschied!

So schockierend es auch scheinen mag, dieser genaue Fehler sorgte in den frühen 1980er Jahren für Aufsehen, als das System zur Aufzeichnung des Werts der Vancouver Stock Exchange den Gesamtindexwert abschnitt auf drei Dezimalstellen anstatt zu runden. Rundungsfehler haben swayed Wahlen und führten sogar zu http://www-users.math.umn.edu/~arnold/disasters/patriot .html [Tod].

Es ist wichtig, wie Sie Zahlen runden, und als verantwortungsbewusster Entwickler und Software-Designer müssen Sie wissen, was die häufigsten Probleme sind und wie Sie damit umgehen. Lassen Sie uns die verschiedenen Rundungsmethoden untersuchen und untersuchen, wie Sie sie in reinem Python implementieren können.

Eine Menagerie von Methoden

Es gibt eine plethora von Rundungsstrategien, jede mit Vor- und Nachteilen. In diesem Abschnitt erfahren Sie mehr über einige der gängigsten Techniken und wie sie Ihre Daten beeinflussen können.

Kürzung

Die einfachste, wenn auch gröbste Methode zum Runden einer Zahl besteht darin, die Zahl auf eine bestimmte Anzahl von Ziffern zu kürzen. Wenn Sie eine Zahl abschneiden, ersetzen Sie jede Ziffer nach einer bestimmten Position durch 0. Hier sind einige Beispiele:

Value Truncated To Result

12.345

Tens place

10

12.345

Ones place

12

12.345

Tenths place

12.3

12.345

Hundredths place

12.34

Sie haben bereits eine Möglichkeit gesehen, dies in der Funktion "+ truncate () +" über den Link zu implementieren: # Wie viel Einfluss kann das Runden haben [Wie viel Einfluss kann das Runden haben?]. In dieser Funktion wurde die Eingabenummer auf drei Dezimalstellen abgeschnitten durch:

  • Multiplizieren Sie die Zahl mit "+ 1000 +", um den Dezimalpunkt um drei Stellen nach rechts zu verschieben

  • Nehmen Sie den ganzzahligen Teil dieser neuen Zahl mit + int () + *Verschieben der Dezimalstelle um drei Stellen nach links durch Teilen durch "+ 1000 +"

Sie können diesen Vorgang verallgemeinern, indem Sie "+ 1000 +" durch die Zahl 10 "ersetzen (" + 10 + "auf die pe Potenz angehoben), wobei p die Anzahl der Dezimalstellen ist, auf die abgeschnitten werden soll:

def truncate(n, decimals=0):
    multiplier = 10*  *decimals
    return int(n* multiplier)/multiplier

In dieser Version von "+ truncate () " ist das zweite Argument standardmäßig " 0 ". Wenn also kein zweites Argument an die Funktion übergeben wird, gibt " truncate () +" den ganzzahligen Teil einer beliebigen Zahl zurück an ihn weitergegeben.

Die Funktion + truncate () + funktioniert sowohl für positive als auch für negative Zahlen:

>>>

>>> truncate(12.5)
12.0

>>> truncate(-5.963, 1)
-5.9

>>> truncate(1.625, 2)
1.62

Sie können sogar eine negative Zahl an + Dezimalstellen + übergeben, um die Ziffern links vom Dezimalpunkt abzuschneiden:

>>>

>>> truncate(125.6, -1)
120.0

>>> truncate(-1374.25, -3)
-1000.0

Wenn Sie eine positive Zahl abschneiden, runden Sie sie ab. Ebenso rundet das Abschneiden einer negativen Zahl diese Zahl auf. In gewissem Sinne ist das Abschneiden eine Kombination von Rundungsmethoden, abhängig vom Vorzeichen der Zahl, die Sie runden.

Schauen wir uns jede dieser Rundungsmethoden einzeln an, beginnend mit der Rundung.

Aufrunden

Die zweite Rundungsstrategie, die wir betrachten werden, heißt "Aufrunden". Diese Strategie rundet eine Zahl immer auf eine bestimmte Anzahl von Ziffern auf. Die folgende Tabelle fasst diese Strategie zusammen:

Value Round Up To Result

12.345

Tens place

20

12.345

Ones place

13

12.345

Tenths place

12.4

12.345

Hundredths place

12.35

Um die Aufrundungsstrategie in Python zu implementieren, verwenden wir die Funktion https://docs.python.org/3/library/math.html#math.ceil [+ lid () +] aus dem https ://docs.python.org/3/library/math.html [+ math +] Modul.

Die Funktion + lid () + hat ihren Namen vom Begriff „Decke“, der in der Mathematik verwendet wird, um die nächste Ganzzahl zu beschreiben, die größer oder gleich einer bestimmten Zahl ist.

Jede Zahl, die keine ganze Zahl ist, liegt zwischen zwei aufeinanderfolgenden ganzen Zahlen. Zum Beispiel liegt die Zahl "+ 1.2 " im Intervall zwischen " 1 " und " 2 ". Die „Obergrenze“ ist der größere der beiden Endpunkte des Intervalls. Der kleinere der beiden Endpunkte wird als "Boden" bezeichnet. Somit ist die Decke von " 1,2 " " 2 " und der Boden von " 1,2 " ist " 1 +".

In der Mathematik ordnet eine spezielle Funktion namens Deckenfunktion jede Zahl ihrer Decke zu. Damit die Deckenfunktion Ganzzahlen akzeptieren kann, wird die Obergrenze einer Ganzzahl als Ganzzahl selbst definiert. Die Obergrenze der Zahl "+ 2 " ist also " 2 +".

In Python implementiert + math.ceil () + die Deckenfunktion und gibt immer die nächste Ganzzahl zurück, die größer oder gleich der Eingabe ist:

>>>

>>> import math

>>> math.ceil(1.2)
2

>>> math.ceil(2)
2

>>> math.ceil(-0.5)
0

Beachten Sie, dass die Obergrenze von "+ -0,5 " " 0 " ist, nicht " -1 ". Dies ist sinnvoll, da " 0 " die nächste Ganzzahl zu " -0,5 " ist, die größer oder gleich " -0,5 +" ist.

Schreiben wir eine Funktion namens "+ round_up () +", die die Strategie "Aufrunden" implementiert:

def round_up(n, decimals=0):
    multiplier = 10 * *decimals
    return math.ceil(n* multiplier)/multiplier

Möglicherweise stellen Sie fest, dass + round_up () + sehr nach + truncate () + aussieht. Zuerst wird der Dezimalpunkt in "+ n " um die richtige Anzahl von Stellen nach rechts verschoben, indem " n " mit "+10 * *Dezimalstellen +" multipliziert wird. Dieser neue Wert wird mit ` math.ceil () +` auf die nächste Ganzzahl aufgerundet, und dann wird der Dezimalpunkt durch Teilen durch +10* *Dezimalstellen + nach links verschoben.

Dieses Muster des Verschiebens des Dezimalpunkts, Anwenden einer Rundungsmethode zum Runden auf eine Ganzzahl und anschließendes Verschieben des Dezimalpunkts wird immer wieder auftreten, wenn wir weitere Rundungsmethoden untersuchen. Dies ist schließlich der mentale Algorithmus, mit dem wir Menschen Zahlen von Hand runden.

Schauen wir uns an, wie gut + round_up () + für verschiedene Eingaben funktioniert:

>>>

>>> round_up(1.1)
2.0

>>> round_up(1.23, 1)
1.3

>>> round_up(1.543, 2)
1.55

Genau wie bei + truncate () + können Sie einen negativen Wert an + decimals + übergeben:

>>>

>>> round_up(22.45, -1)
30.0

>>> round_up(1352, -2)
1400

Wenn Sie eine negative Zahl an "+ Dezimalstellen " übergeben, wird die Zahl im ersten Argument von " round_up () +" auf die richtige Anzahl von Stellen links vom Dezimalpunkt gerundet.

Erraten Sie, was + round_up (-1.5) + zurückgibt:

>>>

>>> round_up(-1.5)
-1.0

Ist "+ -1.0 +" das, was Sie erwartet haben?

Wenn Sie die Logik untersuchen, die bei der Definition von "+ round_up () " verwendet wird - insbesondere die Funktionsweise der Funktion " math.ceil () " -, ist es sinnvoll, dass " round_up (-1.5) " zurückgibt " + -1,0 + `. Einige Leute erwarten jedoch natürlich eine Symmetrie um Null, wenn Zahlen gerundet werden. Wenn also " 1,5 " auf " 2 " aufgerundet wird, sollte " -1,5 " auf " -2 +" aufgerundet werden.

Lassen Sie uns eine Terminologie festlegen. Für unsere Zwecke verwenden wir die Begriffe "Aufrunden" und "Abrunden" gemäß dem folgenden Diagramm:

Beim Aufrunden wird in der Zahlenreihe immer eine Zahl nach rechts gerundet, beim Runden wird in der Zahlenreihe immer eine Zahl nach links gerundet.

Abrunden

Das Gegenstück zum "Aufrunden" ist die "Abrunden" -Strategie, bei der eine Zahl immer auf eine bestimmte Anzahl von Stellen abgerundet wird. Hier einige Beispiele, die diese Strategie veranschaulichen:

Value Rounded Down To Result

12.345

Tens place

10

12.345

Ones place

12

12.345

Tenths place

12.3

12.345

Hundredths place

12.34

Um die Abrundungsstrategie in Python zu implementieren, können wir denselben Algorithmus verwenden, den wir sowohl für + trunctate () + als auch für + round_up () + verwendet haben. Verschieben Sie zuerst den Dezimalpunkt, runden Sie dann auf eine Ganzzahl und verschieben Sie schließlich den Dezimalpunkt zurück.

In + round_up () + haben wir + math.ceil () + verwendet, um nach dem Verschieben des Dezimalpunkts auf die Obergrenze der Zahl aufzurunden. Für die Abrundungsstrategie müssen wir jedoch nach dem Verschieben des Dezimalpunkts auf den Boden der Zahl runden.

Glücklicherweise verfügt das Modul https://docs.python.org/3/library/math.html [+ math +] über ein https://docs.python.org/3/library/math.html#math .floor [+ floor () +] Funktion, die den Boden seiner Eingabe zurückgibt:

>>>

>>> math.floor(1.2)
1

>>> math.floor(-0.5)
-1

Hier ist die Definition von "+ round_down () +":

def round_down(n, decimals=0):
    multiplier = 10*  *decimals
    return math.floor(n* multiplier)/multiplier

Das sieht genauso aus wie "+ round_up () ", außer dass " math.ceil () " durch " math.floor () +" ersetzt wurde.

Sie können + round_down () + an einigen verschiedenen Werten testen:

>>>

>>> round_down(1.5)
1

>>> round_down(1.37, 1)
1.3

>>> round_down(-0.5)
-1

Die Auswirkungen von + round_up () + und + round_down () + können ziemlich extrem sein. Durch Auf- oder Abrunden der Zahlen in einem großen Datensatz können Sie möglicherweise eine Menge Präzision entfernen und die aus den Daten vorgenommenen Berechnungen drastisch ändern.

Bevor wir weitere Rundungsstrategien besprechen, lassen Sie uns einen Moment darüber sprechen, wie durch Rundungen Ihre Daten verzerrt werden können.

Zwischenspiel: Rundungsverzerrung

Sie haben jetzt drei Rundungsmethoden gesehen: + truncate () +, + round_up () + und + round_down () +. Alle drei dieser Techniken sind ziemlich grob, wenn es darum geht, eine angemessene Genauigkeit für eine bestimmte Anzahl beizubehalten.

Es gibt einen wichtigen Unterschied zwischen "+ truncate () " und " round_up () " und " round_down () +", der einen wichtigen Aspekt der Rundung hervorhebt: Symmetrie um Null.

Denken Sie daran, dass + round_up () + um Null nicht symmetrisch ist. In mathematischen Begriffen ist eine Funktion f (x) um Null symmetrisch, wenn für einen beliebigen Wert von x f (x) + f (-x) = 0 ist. Zum Beispiel gibt + round_up (1.5) + + 2 + zurück, aber + round_up (-1.5) + gibt + -1 + zurück. Die Funktion `+ round_down () + ist auch um 0 nicht symmetrisch.

Andererseits ist die Funktion + truncate () + _ um Null symmetrisch. Dies liegt daran, dass nach dem Verschieben des Dezimalpunkts nach rechts + truncate () + die verbleibenden Ziffern abschneidet. Wenn der Anfangswert positiv ist, bedeutet dies eine Abrundung der Zahl. Negative Zahlen werden aufgerundet. Also gibt + truncate (1.5) + + 1 + zurück und + truncate (-1.5) + gibt + -1 + `zurück.

Das Konzept der Symmetrie führt den Begriff der Rundungsverzerrung ein, der beschreibt, wie sich die Rundung auf numerische Daten in einem Datensatz auswirkt.

Die Aufrundungsstrategie hat eine Rundung in Richtung einer positiven Unendlichkeitsverzerrung , da der Wert immer in Richtung einer positiven Unendlichkeit aufgerundet wird. Ebenso hat die Abrundungsstrategie eine Runde in Richtung einer negativen Unendlichkeitsverzerrung .

Die Strategie „Abschneiden“ zeigt eine Runde in Richtung einer negativen Unendlichkeitsverzerrung bei positiven Werten und eine Runde in Richtung einer positiven Unendlichkeit bei negativen Werten. Rundungsfunktionen mit diesem Verhalten sollen im Allgemeinen eine Rundung gegen Null haben.

Mal sehen, wie das in der Praxis funktioniert. Betrachten Sie die folgende Liste von Floats:

>>>

>>> data = [1.25, -2.67, 0.43, -1.79, 4.32, -8.19]

Berechnen wir den Mittelwert der Werte in "+ data " mit der Funktion https://docs.python.org/3/library/statistics.html#statistics.mean [` statistics.mean () +`]:

>>>

>>> import statistics

>>> statistics.mean(data)
-1.1083333333333332

Wenden Sie nun jeweils "+ round_up () ", " round_down () " und " truncate () " in einem https://dbader.org/blog/list-dict-set-comprehensions-in- an Python [Listenverständnis], um jede Zahl in ` Daten +` auf eine Dezimalstelle zu runden und den neuen Mittelwert zu berechnen:

>>>

>>> ru_data = [round_up(n, 1) for n in data]
>>> ru_data
[1.3, -2.6, 0.5, -1.7, 4.4, -8.1]
>>> statistics.mean(ru_data)
-1.0333333333333332

>>> rd_data = [round_down(n, 1) for n in data]
>>> statistics.mean(rd_data)
-1.1333333333333333

>>> tr_data = [truncate(n, 1) for n in data]
>>> statistics.mean(tr_data)
-1.0833333333333333

Nachdem jede Zahl in "+ data " aufgerundet wurde, beträgt der neue Mittelwert ungefähr " -1.033 ", was größer ist als der tatsächliche Mittelwert von " 1.108 ". Durch Abrunden wird der Mittelwert nach unten auf etwa +1,133 + verschoben. Der Mittelwert der abgeschnittenen Werte liegt bei " -1,08 +" und liegt dem tatsächlichen Mittelwert am nächsten.

Dieses Beispiel bedeutet nicht, dass Sie immer abschneiden sollten, wenn Sie einzelne Werte runden müssen, während Sie einen Mittelwert so genau wie möglich beibehalten. Die Liste "+ Daten " enthält eine gleiche Anzahl positiver und negativer Werte. Die Funktion ` truncate () ` verhält sich wie ` round_up () ` in einer Liste aller positiven Werte und genauso wie ` round_down () +` in einer Liste aller negativen Werte.

In diesem Beispiel wird die Auswirkung der Rundungsverzerrung auf Werte veranschaulicht, die aus gerundeten Daten berechnet wurden. Sie müssen diese Effekte berücksichtigen, wenn Sie Schlussfolgerungen aus gerundeten Daten ziehen.

In der Regel möchten Sie beim Runden auf die nächste Zahl mit einer bestimmten Genauigkeit runden, anstatt nur alles auf- oder abzurunden.

Wenn Sie beispielsweise aufgefordert werden, die Zahlen "+ 1,23 " und " 1,28 " auf eine Dezimalstelle zu runden, würden Sie wahrscheinlich schnell mit " 1,2 " und " 1,3 " antworten. Die Funktionen ` truncate () `, ` round_up () ` und ` round_down () +` machen so etwas nicht.

Was ist mit der Zahl + 1.25 +? Sie denken wahrscheinlich sofort daran, dies auf "+ 1,3 " zu runden, aber in Wirklichkeit ist " 1,25 " gleich weit von " 1,2 " und " 1,3 " entfernt. In gewissem Sinne sind " 1,2 " und " 1,3 " die Zahlen, die " 1,25 " mit einer Genauigkeit von einer Dezimalstelle am nächsten kommen. Die Zahl " 1,25 " wird in Bezug auf " 1,2 " und " 1,3 +" als Krawatte bezeichnet. In solchen Fällen müssen Sie einen Tiebreaker zuweisen.

Die Art und Weise, wie den meisten Menschen das Brechen von Bindungen beigebracht wird, besteht darin, auf die größere der beiden möglichen Zahlen zu runden.

Aufrunden

Die Strategie „Aufrunden der Hälfte“ rundet jede Zahl mit der angegebenen Genauigkeit auf die nächste Zahl und unterbricht die Verbindungen durch Aufrunden. Hier sind einige Beispiele:

Value Round Half Up To Result

13.825

Tens place

10

13.825

Ones place

14

13.825

Tenths place

13.8

13.825

Hundredths place

13.83

Um die Strategie „Aufrunden der Hälfte“ in Python zu implementieren, verschieben Sie den Dezimalpunkt wie gewohnt um die gewünschte Anzahl von Stellen nach rechts. An diesem Punkt müssen Sie jedoch feststellen können, ob die Ziffer unmittelbar nach dem verschobenen Dezimalpunkt kleiner oder größer als oder gleich "+ 5 +" ist.

Eine Möglichkeit, dies zu tun, besteht darin, dem verschobenen Wert "+ 0,5 " hinzuzufügen und dann mit " math.floor () +" abzurunden. Dies funktioniert, weil:

  • Wenn die Ziffer auf der ersten Dezimalstelle des verschobenen Werts kleiner als fünf ist, ändert das Hinzufügen von "+ 0,5 " den ganzzahligen Teil des verschobenen Werts nicht, sodass die Grundfläche gleich dem ganzzahligen Teil ist. *Wenn die erste Ziffer nach der Dezimalstelle größer oder gleich " 5 " ist, erhöht das Hinzufügen von " 0,5 " den ganzzahligen Teil des verschobenen Werts um " 1 +", sodass der Boden diesem Wert entspricht größere ganze Zahl.

So sieht das in Python aus:

def round_half_up(n, decimals=0):
    multiplier = 10* * decimals
    return math.floor(n*multiplier + 0.5)/multiplier

Beachten Sie, dass + round_half_up () + sehr nach + round_down () + aussieht. Dies mag etwas kontraintuitiv sein, aber intern wird "+ round_half_up () " nur abgerundet. Der Trick besteht darin, nach dem Verschieben des Dezimalpunkts das " 0,5 +" zu addieren, damit das Ergebnis der Abrundung mit dem erwarteten Wert übereinstimmt.

Testen wir + round_half_up () + an einigen Werten, um zu sehen, ob es funktioniert:

>>>

>>> round_half_up(1.23, 1)
1.2

>>> round_half_up(1.28, 1)
1.3

>>> round_half_up(1.25, 1)
1.3

Da + round_half_up () + immer Bindungen durch Runden auf den größeren der beiden möglichen Werte unterbricht, werden negative Werte wie + -1.5 + auf + -1 + gerundet, nicht auf + -2 +:

>>>

>>> round_half_up(-1.5)
-1.0

>>> round_half_up(-1.25, 1)
-1.2

Toll! Sie können nun endlich das Ergebnis erhalten, dass Ihnen die eingebaute Funktion + round () + verweigert wurde:

>>>

>>> round_half_up(2.5)
3.0

Bevor Sie jedoch zu aufgeregt werden, wollen wir sehen, was passiert, wenn Sie versuchen, "+ -1,225 " auf " 2 +" Dezimalstellen zu runden:

>>>

>>> round_half_up(-1.225, 2)
-1.23

Warten. Wir haben gerade diskutiert, wie Bindungen auf den größeren der beiden möglichen Werte gerundet werden. + -1.225 + liegt genau in der Mitte von + -1.22 + und + -1.23 +. Da "+ -1,22 " der größere dieser beiden ist, sollte " round_half_up (-1,225, 2) " " -1,22 " zurückgeben. Aber stattdessen haben wir " -1,23 +".

Gibt es einen Fehler in der Funktion + round_half_up () +?

Wenn "+ round_half_up () +" + -1,225 + "auf zwei Dezimalstellen rundet, multipliziert es als erstes" + -1,225 + "mit" + 100 + ". Stellen wir sicher, dass dies wie erwartet funktioniert:

>>>

>>> -1.225 *100
-122.50000000000001

Nun …​ das ist falsch! Aber es erklärt, warum + round_half_up (-1.225, 2) + -1,23 zurückgibt. Fahren wir Schritt für Schritt mit dem Algorithmus "+ round_half_up () " fort und verwenden " _ +" in der REPL, um den letzten bei jedem Schritt ausgegebenen Wert abzurufen:

>>>

>>> _ + 0.5
-122.00000000000001

>>> math.floor(_)
-123

>>> _/100
-1.23

Obwohl "+ -122.00000000000001 " wirklich nahe an " -122 " liegt, ist die nächste Ganzzahl, die kleiner oder gleich ist, " -123 ". Wenn der Dezimalpunkt nach links verschoben wird, ist der Endwert " -1,23 +".

Nun wissen Sie, wie + round_half_up (-1.225, 2) + + -1,23 + zurückgibt, obwohl es keinen logischen Fehler gibt, aber warum sagt Python, dass + -1.225* 100 + `` + - ist 122.50000000000001 + `? Gibt es einen Fehler in Python?

*Nebenbei:* Geben Sie in einer Python-Interpretersitzung Folgendes ein:

>>>

>>> 0.1 + 0.1 + 0.1
0.30000000000000004

Dies zum ersten Mal zu sehen, kann ziemlich schockierend sein, aber dies ist ein klassisches Beispiel für Gleitkomma-Darstellungsfehler . Es hat nichts mit Python zu tun. Der Fehler hat damit zu tun, wie Maschinen Gleitkommazahlen im Speicher speichern.

Die meisten modernen Computer speichern Gleitkommazahlen als binäre Dezimalstellen mit einer Genauigkeit von 53 Bit. Nur Zahlen mit endlichen binären Dezimaldarstellungen, die in 53 Bit ausgedrückt werden können, werden als exakter Wert gespeichert. Nicht jede Zahl hat eine endliche binäre Dezimaldarstellung.

Zum Beispiel hat die Dezimalzahl "+ 0.1 " eine endliche Dezimaldarstellung, aber eine unendliche binäre Darstellung. So wie der Bruch 1/3 nur in Dezimalzahlen als sich unendlich wiederholende Dezimalzahl "+0,333 ... +" dargestellt werden kann, kann der Bruch " 1/10 +" nur in Binärform als sich unendlich wiederholende Dezimalzahl "+0,0001100110011" ausgedrückt werden …​ + `.

Ein Wert mit einer unendlichen binären Darstellung wird auf einen ungefähren Wert gerundet, der im Speicher gespeichert werden soll. Die Methode, die die meisten Maschinen zum Runden verwenden, wird gemäß dem Standard IEEE-754 festgelegt, der das Runden auf den nächsten darstellbaren binären Bruch angibt.

Die Python-Dokumente haben einen Abschnitt namens Floating Point Arithmetic: Issues and Limitations, der Folgendes über die Zahl 0.1 zu sagen hat:

_ _ Wenn Python auf den meisten Computern den wahren Dezimalwert der für + 0.1 + gespeicherten binären Näherung drucken würde, müsste es angezeigt werden

>>>

>>> 0.1
0.1000000000000000055511151231257827021181583404541015625

Das sind mehr Ziffern, als die meisten Leute für nützlich halten. Daher hält Python die Anzahl der Ziffern überschaubar, indem stattdessen ein gerundeter Wert angezeigt wird

>>>

>>> 1/10
0.1

Denken Sie daran, obwohl das gedruckte Ergebnis wie der genaue Wert von "+ 1/10 +" aussieht, ist der tatsächlich gespeicherte Wert der nächste darstellbare binäre Bruch. (Source) _ _

Eine ausführlichere Abhandlung über Gleitkomma-Arithmetik finden Sie in David Goldbergs Artikel Was jeder Informatiker über Gleitkomma wissen sollte Arithmetik, ursprünglich veröffentlicht in der Zeitschrift ACM Computing Surveys, Vol. 23, No. 1. März 1991.

Die Tatsache, dass Python sagt, dass "+ -1.225 *100 " " -122.50000000000001 +" ist, ist ein Artefakt eines Gleitkomma-Darstellungsfehlers. Sie fragen sich vielleicht: "Okay, aber gibt es eine Möglichkeit, dies zu beheben?" Eine bessere Frage, die Sie sich stellen sollten, lautet: "Muss ich das beheben?"

Gleitkommazahlen haben keine exakte Genauigkeit und sollten daher* nicht *in Situationen verwendet werden, in denen die Genauigkeit von größter Bedeutung ist. Für Anwendungen, bei denen die genaue Genauigkeit erforderlich ist, können Sie die Klasse "+ Decimal " aus Pythons Modul " decimal " verwenden. Im Folgenden erfahren Sie mehr über die Klasse " Dezimal +".

Wenn Sie festgestellt haben, dass Pythons Standardklasse "+ float " für Ihre Anwendung ausreicht, sollten einige gelegentliche Fehler in " round_half_up () +" aufgrund eines Gleitkomma-Darstellungsfehlers kein Problem darstellen.

Nachdem Sie einen Eindruck davon bekommen haben, wie Maschinen Zahlen im Speicher runden, setzen wir unsere Diskussion über Rundungsstrategien fort, indem wir einen anderen Weg suchen, um ein Unentschieden zu lösen.

Abrunden zur Hälfte

Die Strategie „Abrunden der Hälfte“ rundet mit der gewünschten Genauigkeit auf die nächste Zahl, genau wie die Methode „Aufrunden der Hälfte“, mit der Ausnahme, dass die Bindungen durch Runden auf die kleinere der beiden Zahlen unterbrochen werden. Hier sind einige Beispiele:

Value Round Half Down To Result

13.825

Tens place

10

13.825

Ones place

14

13.825

Tenths place

13.8

13.825

Hundredths place

13.82

Sie können die Strategie "Abrunden der Hälfte" in Python implementieren, indem Sie "+ math.floor () " in der Funktion " round_half_up () " durch " math.ceil () " ersetzen und " 0,5 +" subtrahieren anstatt hinzuzufügen:

def round_half_down(n, decimals=0):
    multiplier = 10* * decimals
    return math.ceil(n*multiplier - 0.5)/multiplier

Überprüfen wir + round_half_down () + anhand einiger Testfälle:

>>>

>>> round_half_down(1.5)
1.0

>>> round_half_down(-1.5)
-2.0

>>> round_half_down(2.25, 1)
2.2

Sowohl + round_half_up () + als auch + round_half_down () + haben im Allgemeinen keine Verzerrung. Das Runden von Daten mit vielen Bindungen führt jedoch zu einer Verzerrung. Betrachten Sie als extremes Beispiel die folgende Liste von Zahlen:

>>>

>>> data = [-2.15, 1.45, 4.35, -12.75]

Berechnen wir den Mittelwert dieser Zahlen:

>>>

>>> statistics.mean(data)
-2.275

Berechnen Sie als Nächstes den Mittelwert der Daten, nachdem Sie mit + round_half_up () + und` + round_half_down () + `auf eine Dezimalstelle gerundet haben:

>>>

>>> rhu_data = [round_half_up(n, 1) for n in data]
>>> statistics.mean(rhu_data)
-2.2249999999999996

>>> rhd_data = [round_half_down(n, 1) for n in data]
>>> statistics.mean(rhd_data)
-2.325

Jede Zahl in "+ Daten " ist ein Gleichstand in Bezug auf das Runden auf eine Dezimalstelle. Die Funktion " round_half_up () " führt eine Runde in Richtung einer positiven Unendlichkeitsvorspannung ein, und " round_half_down () +" führt eine Runde in Richtung einer negativen Unendlichkeitsvorspannung ein.

In den verbleibenden Rundungsstrategien werden wir alle Versuche diskutieren, diese Verzerrungen auf unterschiedliche Weise abzumildern.

Rundung auf halbem Weg von Null

Wenn Sie + round_half_up () + und + round_half_down () + genau untersuchen, werden Sie feststellen, dass keine dieser Funktionen um Null symmetrisch ist:

>>>

>>> round_half_up(1.5)
2.0

>>> round_half_up(-1.5)
-1.0

>>> round_half_down(1.5)
1.0

>>> round_half_down(-1.5)
-2.0

Eine Möglichkeit, Symmetrie einzuführen, besteht darin, ein Unentschieden immer von Null weg zu runden. Die folgende Tabelle zeigt, wie dies funktioniert:

Value Round Half Away From Zero To Result

15.25

Tens place

20

15.25

Ones place

15

15.25

Tenths place

15.3

-15.25

Tens place

-20

-15.25

Ones place

-15

-15.25

Tenths place

-15.3

Um die Strategie „Hälfte von Null abrunden“ auf eine Zahl + n + zu implementieren, verschieben Sie wie gewohnt den Dezimalpunkt um eine bestimmte Anzahl von Stellen nach rechts. Dann sehen Sie sich die Ziffer "+ d +" unmittelbar rechts von der Dezimalstelle in dieser neuen Zahl an. An dieser Stelle sind vier Fälle zu berücksichtigen:

  1. Wenn "+ n " positiv ist und " d> = 5 +", runden Sie auf

  2. Wenn "+ n " positiv ist und " d <5 +", runden Sie ab

  3. Wenn "+ n " negativ ist und " d> = 5 +", runden Sie ab

  4. Wenn "+ n " negativ ist und " d <5 +", runden Sie auf

Nach dem Runden nach einer der oben genannten vier Regeln verschieben Sie die Dezimalstelle zurück nach links.

Wenn Sie eine Zahl "+ n " und einen Wert für " Dezimalstellen " angeben, können Sie dies in Python implementieren, indem Sie " round_half_up () " und " round_half_down () +" verwenden:

if n >= 0:
    rounded = round_half_up(n, decimals)
else:
    rounded = round_half_down(n, decimals)

Das ist einfach genug, aber es gibt tatsächlich einen einfacheren Weg!

Wenn Sie zuerst den absoluten Wert von "+ n " mit der in Python integrierten Funktion https://docs.python.org/3/library/functions.html#abs [` abs () `] verwenden, können Sie dies einfach tun Verwenden Sie ` round_half_up () `, um die Zahl zu runden. Dann müssen Sie der gerundeten Zahl nur noch das gleiche Vorzeichen wie " n " geben. Eine Möglichkeit hierfür ist die Verwendung der Funktion https://docs.python.org/3/library/math.html#math.copysign [` math.copysign () +`].

+ math.copysign () + nimmt zwei Zahlen + a + und + b + und gibt + a + mit dem Vorzeichen von + b + zurück:

>>>

>>> math.copysign(1, -2)
-1.0

Beachten Sie, dass + math.copysign () + ein + float + zurückgibt, obwohl beide Argumente Ganzzahlen waren.

Mit + abs () +, + round_half_up () + und + math.copysign () + können Sie die Strategie „Abrunden der Hälfte von Null“ in nur zwei Zeilen von Python implementieren:

def round_half_away_from_zero(n, decimals=0):
    rounded_abs = round_half_up(abs(n), decimals)
    return math.copysign(rounded_abs, n)

In + round_half_away_from_zero () + wird der Absolutwert von + n + mit` + round_half_up () + auf + Dezimalstellen + Dezimalstellen gerundet und dieses Ergebnis der Variablen + round_abs + `zugewiesen. Dann wird das ursprüngliche Vorzeichen von "+ n " mit " math.copysign () " auf " round_abs +" angewendet, und dieser Endwert mit dem richtigen Vorzeichen wird von der Funktion zurückgegeben.

Das Überprüfen von + round_half_away_from_zero () + auf einige verschiedene Werte zeigt, dass sich die Funktion wie erwartet verhält:

>>>

>>> round_half_away_from_zero(1.5)
2.0

>>> round_half_away_from_zero(-1.5)
-2.0

>>> round_half_away_from_zero(-12.75, 1)
-12.8

Die Funktion + round_half_away_from_zero () + rundet Zahlen so, wie die meisten Menschen im Alltag dazu neigen, Zahlen zu runden. + Round_half_away_from_zero () + ist nicht nur die bekannteste Rundungsfunktion, die Sie bisher gesehen haben, sondern eliminiert auch die Rundungsverzerrung in Datensätzen mit einer gleichen Anzahl positiver und negativer Bindungen.

Lassen Sie uns überprüfen, wie gut + round_half_away_from_zero () + die Rundungsverzerrung im Beispiel aus dem vorherigen Abschnitt verringert:

>>>

>>> data = [-2.15, 1.45, 4.35, -12.75]
>>> statistics.mean(data)
-2.275

>>> rhaz_data = [round_half_away_from_zero(n, 1) for n in data]
>>> statistics.mean(rhaz_data)
-2.2750000000000004

Der Mittelwert der Zahlen in + Daten + bleibt fast genau erhalten, wenn Sie jede Zahl in + Daten + mit + round_half_away_from_zero () + auf eine Dezimalstelle runden!

+ Round_half_away_from_zero () + weist jedoch eine Rundungsverzerrung auf, wenn Sie jede Zahl in Datensätzen mit nur positiven Bindungen, nur negativen Bindungen oder mehr Bindungen eines Zeichens als des anderen runden. Die Verzerrung wird nur dann gut gemindert, wenn der Datensatz eine ähnliche Anzahl positiver und negativer Bindungen enthält.

Wie gehen Sie mit Situationen um, in denen sich die Anzahl der positiven und negativen Bindungen drastisch unterscheidet? Die Antwort auf diese Frage schließt den Kreis zu der Funktion, die uns am Anfang dieses Artikels getäuscht hat: Pythons integrierte https://docs.python.org/3/library/functions.html#round [`+ round ( ) + `] Funktion.

Rundung der Hälfte auf Gleichmäßigkeit

Eine Möglichkeit, die Rundungsverzerrung beim Runden von Werten in einem Datensatz zu verringern, besteht darin, Bindungen mit der gewünschten Genauigkeit auf die nächste gerade Zahl zu runden. Hier einige Beispiele, wie das geht:

Value Round Half To Even To Result

15.255

Tens place

20

15.255

Ones place

15

15.255

Tenths place

15.3

15.255

Hundredths place

15.26

Die "Rounding Half to Even" -Strategie ist die Strategie, die von Pythons integrierter "+ round () +" - Funktion verwendet wird, und ist die default-Rundungsregel im IEEE -754 Standard. Diese Strategie funktioniert unter der Annahme, dass die Wahrscheinlichkeiten eines Gleichstands in einem Datensatz, der abgerundet oder aufgerundet wird, gleich sind. In der Praxis ist dies normalerweise der Fall.

Jetzt wissen Sie, warum + round (2.5) + + 2 + `zurückgibt. Es ist kein Fehler. Es ist eine bewusste Designentscheidung, die auf soliden Empfehlungen basiert.

Um sich selbst zu beweisen, dass + round () + wirklich rund macht, probieren Sie es mit ein paar verschiedenen Werten aus:

>>>

>>> round(4.5)
4

>>> round(3.5)
4

>>> round(1.75, 1)
1.8

>>> round(1.65, 1)
1.6

Die Funktion "+ round () +" ist nahezu frei von Verzerrungen, aber nicht perfekt. Beispielsweise kann eine Rundungsverzerrung weiterhin eingeführt werden, wenn die Mehrheit der Bindungen in Ihrem Datensatz auf gerade aufgerundet wird, anstatt abgerundet zu werden. Es gibt Strategien, die die Verzerrung noch besser abschwächen als das „Aufrunden auf die Hälfte“ (https://en.wikipedia.org/wiki/Rounding#Random-based_rounding_of_an_integer[do), aber sie sind etwas dunkel und nur unter extremen Umständen erforderlich.

Schließlich leidet + round () + unter denselben Problemen, die Sie in + round_half_up () + gesehen haben, dank eines Gleitkomma-Darstellungsfehlers:

>>>

>>> # Expected value: 2.68
>>> round(2.675, 2)
2.67

Sie sollten sich nicht mit diesen gelegentlichen Fehlern befassen, wenn die Gleitkommapräzision für Ihre Anwendung ausreicht.

Wenn die Genauigkeit ist von größter Bedeutung ist, sollten Sie die Python-Klasse "+ Decimal +" verwenden.

Die Klasse + Dezimal

Das Python-Modul decimal ist eine der Funktionen der Sprache, die in Batterien enthalten sind und die Sie möglicherweise nicht kennen, wenn Sie Python noch nicht kennen. Das Leitprinzip des Moduls + decimal + finden Sie in der Dokumentation:

_ Dezimal „basiert auf einem Gleitkommamodell, das für Menschen entwickelt wurde und notwendigerweise ein vorrangiges Leitprinzip hat - Computer müssen eine Arithmetik bereitstellen, die genauso funktioniert wie die Arithmetik, die Menschen in der Schule lernen.“ - Auszug aus der dezimalen arithmetischen Spezifikation. (Source) _

Die Vorteile des Moduls + decimal + umfassen:

  • Exakte Dezimaldarstellung : + 0.1 + ist aktuell` + 0.1 + und +0.1 + 0.1 + 0.1 - 0.3 + gibt erwartungsgemäß + 0 + `zurück.

  • Beibehaltung signifikanter Ziffern : Wenn Sie "+ 1,20 " und " 2,50 " hinzufügen, ist das Ergebnis " 3,70 +", wobei die nachfolgende Null beibehalten wird, um die Signifikanz anzuzeigen.

  • Vom Benutzer änderbare Genauigkeit : Die Standardgenauigkeit des Moduls + decimal + beträgt achtundzwanzig Stellen. Dieser Wert kann jedoch vom Benutzer geändert werden, um dem vorliegenden Problem zu entsprechen.

Lassen Sie uns untersuchen, wie die Rundung im Modul "+ Dezimal +" funktioniert. Geben Sie zunächst Folgendes in eine Python-REPL ein:

>>>

>>> import decimal
>>> decimal.getcontext()
Context(
    prec=28,
    rounding=ROUND_HALF_EVEN,
    Emin=-999999,
    Emax=999999,
    capitals=1,
    clamp=0,
    flags=[],
    traps=[
        InvalidOperation,
        DivisionByZero,
        Overflow
    ]
)

+ decimal.getcontext () + gibt ein + Context + Objekt zurück, das den Standardkontext des + decimal + Moduls darstellt. Der Kontext enthält unter anderem die Standardgenauigkeit und die Standardrundungsstrategie.

Wie Sie im obigen Beispiel sehen können, lautet die Standardrundungsstrategie für das Modul "+ decimal " " ROUND_HALF_EVEN ". Dies entspricht der integrierten Funktion " round () +" und sollte für die meisten Zwecke die bevorzugte Rundungsstrategie sein.

Deklarieren wir eine Zahl mit der Klasse "+ decimal " des Moduls " Decimal ". Erstellen Sie dazu eine neue ` Decimal ` Instanz, indem Sie eine ` string +` übergeben, die den gewünschten Wert enthält:

>>>

>>> from decimal import Decimal
>>> Decimal("0.1")
Decimal('0.1')
*Hinweis:* Es ist möglich, eine + Dezimal + -Instanz aus einer Gleitkommazahl zu erstellen, dies führt jedoch sofort zu einem Gleitkomma-Darstellungsfehler. Überprüfen Sie beispielsweise, was passiert, wenn Sie eine + Dezimal + -Instanz aus der Gleitkommazahl + 0,1 + erstellen:

>>>

>>> Decimal(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')

Um die genaue Genauigkeit beizubehalten, müssen Sie aus Zeichenfolgen, die die benötigten Dezimalzahlen enthalten, + Dezimal + Instanzen erstellen.

Testen wir zum Spaß die Behauptung, dass "+ Dezimal +" die exakte Dezimaldarstellung beibehält:

>>>

>>> Decimal('0.1') + Decimal('0.1') + Decimal('0.1')
Decimal('0.3')

Ähhh. Das ist doch befriedigend, oder?

Das Runden einer + Dezimalzahl + erfolgt mit der Methode + .quantize () +:

>>>

>>> Decimal("1.65").quantize(Decimal("1.0"))
Decimal('1.6')

Okay, das sieht wahrscheinlich ein bisschen funky aus, also lasst uns das zusammenfassen. Das Argument + Decimal (" 1.0 ") + in + .quantize () + bestimmt die Anzahl der Dezimalstellen, um die Zahl zu runden. Da "+ 1.0 " eine Dezimalstelle hat, wird die Zahl " 1.65 " auf eine einzelne Dezimalstelle gerundet. Die Standardrundungsstrategie lautet "halbe auf gerade runden", daher lautet das Ergebnis " 1,6 +".

Denken Sie daran, dass die Funktion + round () +, die auch die Strategie „Rundung der Hälfte auf Gleichmäßigkeit“ verwendet, + 2.675 + nicht korrekt auf zwei Dezimalstellen gerundet hat. Anstelle von "+ 2.68 " gibt " round (2.675, 2) " + 2.67 + "zurück. Dank der exakten Dezimaldarstellung der Module " decimal " haben Sie dieses Problem mit der Klasse " Decimal +" nicht:

>>>

>>> Decimal("2.675").quantize(Decimal("1.00"))
Decimal('2.68')

Ein weiterer Vorteil des Moduls "+ Dezimal " besteht darin, dass die Rundung nach dem Ausführen der Arithmetik automatisch erfolgt und signifikante Ziffern erhalten bleiben. Um dies in Aktion zu sehen, ändern wir die Standardgenauigkeit von achtundzwanzig Ziffern auf zwei und fügen dann die Zahlen " 1,23 " und " 2,32 +" hinzu:

>>>

>>> decimal.getcontext().prec = 2
>>> Decimal("1.23") + Decimal("2.32")
Decimal('3.6')

Um die Genauigkeit zu ändern, rufen Sie + decimal.getcontext () + auf und setzen das Attribut + .prec +. Wenn das Festlegen des Attributs für einen Funktionsaufruf für Sie seltsam erscheint, können Sie dies tun, da + .getcontext () + ein spezielles + Context + Objekt zurückgibt, das den aktuellen internen Kontext darstellt, der die vom `+ Dezimal + verwendeten Standardparameter enthält `Modul.

Der genaue Wert von "+ 1,23 " plus " 2,32 " ist " 3,55 ". Da die Genauigkeit jetzt zweistellig ist und die Rundungsstrategie auf den Standardwert "halbe auf gerade runden" eingestellt ist, wird der Wert " 3,55 " automatisch auf " 3,6 +" gerundet.

Um die Standardrundungsstrategie zu ändern, können Sie die Eigenschaft + decimal.getcontect (). Rounding + auf eine von mehreren flags setzen . In der folgenden Tabelle sind diese Flags und die von ihnen implementierte Rundungsstrategie zusammengefasst:

Flag Rounding Strategy

decimal.ROUND_CEILING

Rounding up

decimal.ROUND_FLOOR

Rounding down

decimal.ROUND_DOWN

Truncation

decimal.ROUND_UP

Rounding away from zero

decimal.ROUND_HALF_UP

Rounding half away from zero

decimal.ROUND_HALF_DOWN

Rounding half towards zero

decimal.ROUND_HALF_EVEN

Rounding half to even

decimal.ROUND_05UP

Rounding up and rounding towards zero

Das erste, was zu beachten ist, ist, dass das vom Modul "+ decimal " verwendete Namensschema von dem abweicht, was wir zuvor in diesem Artikel vereinbart haben. Zum Beispiel implementiert ` decimal.ROUND_UP +` die Strategie „Abrunden von Null“, die negative Zahlen tatsächlich abrundet.

Zweitens sehen einige der in der Tabelle genannten Rundungsstrategien möglicherweise ungewohnt aus, da wir sie nicht erörtert haben. Sie haben bereits gesehen, wie "+ decimal.ROUND_HALF_EVEN +" funktioniert. Schauen wir uns also die anderen in Aktion an.

Die Strategie "+ decimal.ROUND_CEILING " funktioniert genauso wie die zuvor definierte Funktion " round_up () +":

>>>

>>> decimal.getcontext().rounding = decimal.ROUND_CEILING

>>> Decimal("1.32").quantize(Decimal("1.0"))
Decimal('1.4')

>>> Decimal("-1.32").quantize(Decimal("1.0"))
Decimal('-1.3')

Beachten Sie, dass die Ergebnisse von + decimal.ROUND_CEILING + um Null nicht symmetrisch sind.

Die Strategie "+ decimal.ROUND_FLOOR " funktioniert genauso wie unsere Funktion " round_down () +":

>>>

>>> decimal.getcontext().rounding = decimal.ROUND_FLOOR

>>> Decimal("1.32").quantize(Decimal("1.0"))
Decimal('1.3')

>>> Decimal("-1.32").quantize(Decimal("1.0"))
Decimal('-1.4')

Wie + decimal.ROUND_CEILING + ist die Strategie + decimal.ROUND_FLOOR + nicht symmetrisch um Null.

Die Strategien + decimal.ROUND_DOWN + und + decimal.ROUND_UP + haben etwas trügerische Namen. Sowohl + ROUND_DOWN + als auch + ROUND_UP + sind um Null symmetrisch:

>>>

>>> decimal.getcontext().rounding = decimal.ROUND_DOWN

>>> Decimal("1.32").quantize(Decimal("1.0"))
Decimal('1.3')

>>> Decimal("-1.32").quantize(Decimal("1.0"))
Decimal('-1.3')

>>> decimal.getcontext().rounding = decimal.ROUND_UP

>>> Decimal("1.32").quantize(Decimal("1.0"))
Decimal('1.4')

>>> Decimal("-1.32").quantize(Decimal("1.0"))
Decimal('-1.4')

Die Strategie + decimal.ROUND_DOWN + rundet Zahlen gegen Null, genau wie die Funktion + truncate () +. Auf der anderen Seite rundet + decimal.ROUND_UP + alles von Null weg. Dies ist ein klarer Bruch mit der Terminologie, der wir weiter oben in diesem Artikel zugestimmt haben. Denken Sie also daran, wenn Sie mit dem Modul "+ decimal +" arbeiten.

Es gibt drei Strategien im Modul "+ Dezimal ", die eine differenziertere Rundung ermöglichen. Die Methode ` decimal.ROUND_HALF_UP +` rundet alles auf die nächste Zahl und unterbricht Bindungen, indem sie von Null wegrundet:

>>>

>>> decimal.getcontext().rounding = decimal.ROUND_HALF_UP

>>> Decimal("1.35").quantize(Decimal("1.0"))
Decimal('1.4')

>>> Decimal("-1.35").quantize(Decimal("1.0"))
Decimal('-1.4')

Beachten Sie, dass + decimal.ROUND_HALF_UP + genauso funktioniert wie unser + round_half_away_from_zero () + und nicht wie + round_half_up () +.

Es gibt auch eine + decimal.ROUND_HALF_DOWN + Strategie, die Bindungen durch Runden auf Null bricht:

>>>

>>> decimal.getcontext().rounding = decimal.ROUND_HALF_DOWN

>>> Decimal("1.35").quantize(Decimal("1.0"))
Decimal('1.3')

>>> Decimal("-1.35").quantize(Decimal("1.0"))
Decimal('-1.3')

Die endgültige Rundungsstrategie, die im Modul "+ Dezimal +" verfügbar ist, unterscheidet sich stark von allem, was wir bisher gesehen haben:

>>>

>>> decimal.getcontext().rounding = decimal.ROUND_05UP

>>> Decimal("1.38").quantize(Decimal("1.0"))
Decimal('1.3')

>>> Decimal("1.35").quantize(Decimal("1.0"))
Decimal('1.3')

>>> Decimal("-1.35").quantize(Decimal("1.0"))
Decimal('-1.3')

In den obigen Beispielen sieht es so aus, als ob + decimal.ROUND_05UP + alles gegen Null rundet. Genau so funktioniert + decimal.ROUND_05UP +, es sei denn, das Ergebnis der Rundung endet mit + 0 + oder + 5 +. In diesem Fall wird die Zahl von Null gerundet:

>>>

>>> Decimal("1.49").quantize(Decimal("1.0"))
Decimal('1.4')

>>> Decimal("1.51").quantize(Decimal("1.0"))
Decimal('1.6')

Im ersten Beispiel wird die Zahl "+ 1,49 " zuerst mit der zweiten Dezimalstelle auf Null gerundet, wodurch " 1,4 " erzeugt wird. Da " 1.4 " nicht mit " 0 " oder " 5 " endet, bleibt es unverändert. Andererseits wird " 1,51 " in der zweiten Dezimalstelle gegen Null gerundet, was zu der Zahl " 1,5 " führt. Dies endet mit einem " 5 ", sodass die erste Dezimalstelle von Null auf " 1,6 +" gerundet wird.

In diesem Abschnitt haben wir uns nur auf die Rundungsaspekte des Moduls + decimal + konzentriert. Es gibt eine Vielzahl anderer Funktionen, die + decimal + zu einer hervorragenden Wahl für Anwendungen machen, bei denen die Standard-Gleitkommapräzision unzureichend ist, z. B. Bankgeschäfte und einige Probleme beim wissenschaftlichen Rechnen.

Weitere Informationen zu + Decimal + finden Sie in den Python-Dokumenten unter Quick-start Tutorial.

Wenden wir uns als Nächstes zwei Grundnahrungsmitteln für Pythons Stacks für wissenschaftliche Datenverarbeitung und Datenwissenschaft zu: NumPy und Pandas.

Rundung von NumPy-Arrays

In den Bereichen data science und Scientific Computing speichern Sie Ihre Daten häufig als https://docs.scipy.org/doc/numpy/reference/arrays .html [NumPy + array +]. Eine der leistungsstärksten Funktionen von NumPy ist die Verwendung von vectorization and Broadcasting, um Operationen auf ein gesamtes Array gleichzeitig anstatt auf jeweils ein Element anzuwenden.

Lassen Sie uns einige Daten generieren, indem wir ein 3 × 4-NumPy-Array von Pseudozufallszahlen erstellen:

>>>

>>> import numpy as np
>>> np.random.seed(444)

>>> data = np.random.randn(3, 4)
>>> data
array([[First, we seed the `+np.random+` module so that you can easily reproduce the output. Then a 3×4 NumPy array of floating-point numbers is created with `+np.random.randn()+`.

*Note:* You’ll need to `+pip3 install numpy+` before typing the above code into your REPL if you don’t already have NumPy in your environment. If you installed Python with https://www.anaconda.com/[Anaconda], you’re already set!

If you haven’t used NumPy before, you can get a quick introduction in the https://realpython.com/numpy-array-programming/#getting-into-shape-intro-to-numpy-arrays[Getting Into Shape] section of Brad Solomon’s https://realpython.com/numpy-array-programming/[Look Ma, No For-Loops: Array Programming With NumPy] here at Real Python.

For more information on NumPy’s https://docs.scipy.org/doc/numpy/reference/routines.random.html[random] module, check out the https://realpython.com/python-random/#prngs-for-arrays-numpyrandom[PRNG’s for Arrays] section of Brad’s https://realpython.com/python-random/[Generating Random Data in Python (Guide)].

To round all of the values in the `+data+` array, you can pass `+data+` as the argument to the https://docs.scipy.org/doc/numpy/reference/generated/numpy.around.html#numpy.around[`+np.around()+`] function. The desired number of decimal places is set with the `+decimals+` keyword argument. The round half to even strategy is used, just like Python’s built-in `+round()+` function.

For example, the following rounds all of the values in `+data+` to three decimal places:

[.repl-toggle]#>>>#

[source,python,repl]

>>> np.around (data, decimals = 3) array ([[np.around () + ist dem Gleitkomma-Darstellungsfehler ausgeliefert, genau wie + round () + `.

Beispielsweise ist der Wert in der dritten Zeile der ersten Spalte im Array "+ data " " 0.20851975 ". Wenn Sie dies mit der Strategie "Halbieren auf halbieren" auf drei Dezimalstellen runden, erwarten Sie einen Wert von " 0,208 ". In der Ausgabe von ` np.around () ` sehen Sie jedoch, dass der Wert auf ` 0.209 ` gerundet ist. Der Wert " 0,3775384 " in der ersten Zeile der zweiten Spalte rundet jedoch korrekt auf " 0,378 +".

Wenn Sie die Daten in Ihrem Array auf Ganzzahlen runden müssen, bietet NumPy mehrere Optionen:

Die Funktion + np.ceil () + rundet jeden Wert im Array auf die nächste Ganzzahl, die größer oder gleich dem ursprünglichen Wert ist:

>>>

>>> np.ceil(data)
array([[Hey, we discovered a new number! Negative zero!

Actually, the https://en.wikipedia.org/wiki/IEEE_754[IEEE-754] standard requires the implementation of both a positive and negative zero. What possible use is there for something like this? Wikipedia knows the answer:

____
Informally, one may use the notation “`+−0+`” for a negative value that was rounded to zero. This notation may be useful when a negative sign is significant; for example, when tabulating Celsius temperatures, where a negative sign means below freezing. (https://en.wikipedia.org/wiki/Signed_zero#Scientific_uses[Source])
____

To round every value down to the nearest integer, use `+np.floor()+`:

[.repl-toggle]#>>>#

[source,python,repl]

>>> np.floor (data) array ([[Sie können jeden Wert auch mit + np.trunc () + auf seine Ganzzahlkomponente kürzen:

>>>

>>> np.trunc(data)
array([[Finally, to round to the nearest integer using the “rounding half to even” strategy, use `+np.rint()+`:

[.repl-toggle]#>>>#

[source,python,repl]

>>> np.rint (data) array ([[Möglicherweise haben Sie bemerkt, dass viele der zuvor diskutierten Rundungsstrategien hier fehlen. In den allermeisten Situationen ist die Funktion + around () + alles, was Sie brauchen. Wenn Sie eine andere Strategie implementieren müssen, z. B. "+ round_half_up () +", können Sie dies mit einer einfachen Änderung tun:

def round_half_up(n, decimals=0):
    multiplier = 10* * decimals
    # Replace math.floor with np.floor
    return np.floor(n*multiplier + 0.5)/multiplier

Dank NumPys vectorized Operations funktioniert dies genau so, wie Sie es erwarten:

>>>

>>> round_half_up(data, decimals=2)
array([[Now that you’re a NumPy rounding master, let’s take a look at Python’s other data science heavy-weight: the Pandas library.

=== Rounding Pandas `+Series+` and `+DataFrame+`

The https://pandas.pydata.org/pandas-docs/stable/[Pandas] library has become a staple for data scientists and data analysts who work in Python. In the words of Real Python’s own Joe Wyndham:

____
Pandas is a game-changer for data science and analytics, particularly if you came to Python because you were searching for something more powerful than Excel and VBA. (https://realpython.com/fast-flexible-pandas/[Source])
____

*Note:* Before you continue, you’ll need to `+pip3 install pandas+` if you don’t already have it in your environment. As was the case for NumPy, if you installed Python with https://www.anaconda.com/[Anaconda], you should be ready to go!

The two main Pandas data structures are the `+DataFrame+`, which in very loose terms works sort of like an Excel spreadsheet, and the `+Series+`, which you can think of as a column in a spreadsheet. Both `+Series+` and `+DataFrame+` objects can also be rounded efficiently using the `+Series.round()+` and `+DataFrame.round()+` methods:

[.repl-toggle]#>>>#

[source,python,repl]

>>> Pandas als pd importieren

>>> # np.random erneut säen, wenn Sie Ihre REPL seit dem letzten Beispiel geschlossen haben >>> np.random.seed (444)

>>> series = pd.Series (np.random.randn (4)) >>> series 0 0.357440 1 0.377538 2 1.382338 3 1.175549 dtype: float64

>>> series.round (2) 0 0,36 1 0,38 2 1,38 3 1,18 dtype: float64

>>> df = pd.DataFrame (np.random.randn (3, 3), Spalten = ["A", "B", "C"]) >>> df ABC 0 -0.939276 -1.143150 -0.542440 1 - 0,548708 0,208520 0,212690 2 1,268021 -0,807303 -3,303072

>>> df.round (3) A B C 0 -0,939 -1,143 -0,542 1 -0,549 0,209 0,213 2 1,268 -0,807 -3,303

The `+DataFrame.round()+` method can also accept a dictionary or a `+Series+`, to specify a different precision for each column. For instance, the following examples show how to round the first column of `+df+` to one decimal place, the second to two, and the third to three decimal places:

[.repl-toggle]#>>>#

[source,python,repl]

>>> # Geben Sie die spaltenweise Genauigkeit mit einem Wörterbuch an >>> df.round ({"A": 1, "B": 2, "C": 3}) ABC 0 -0.9 -1.14 -0.542 1 -0,5 0,21 0,213 2 1,3 -0,81 -3,303

>>> # Geben Sie die spaltenweise Genauigkeit mit einer Reihe an >>> Dezimalstellen = pd.Series ([1, 2, 3], index = ["A", "B", "C"]) >>> df.round (Dezimalstellen) ABC 0 -0,9 -1,14 -0,542 1 -0,5 0,21 0,213 2 1,3 -0,81 -3,303

If you need more rounding flexibility, you can apply NumPy’s `+floor()+`, `+ceil()+`, and `+rint()+` functions to Pandas `+Series+` and `+DataFrame+` objects:

[.repl-toggle]#>>>#

[source,python,repl]

>>> np.floor (df) A B C 0 -1,0 -2,0 -1,0 1 -1,0 0,0 0,0 2 1,0 -1,0 -4,0

>>> np.ceil (df) A B C 0 -0,0 -1,0 -0,0 1 -0,0 1,0 1,0 2 2,0 -0,0 -3,0

>>> np.rint (df) A B C 0 -1,0 -1,0 -1,0 1 -1,0 0,0 0,0 2 1,0 -1,0 -3,0

The modified `+round_half_up()+` function from the previous section will also work here:

[.repl-toggle]#>>>#

[source,python,repl]

>>> round_half_up (df, Dezimalstellen = 2) A B C 0 -0,94 -1,14 -0,54 1 -0,55 0,21 0,21 2 1,27 -0,81 -3,30

Congratulations, you’re well on your way to rounding mastery! You now know that there are more ways to round a number than there are taco combinations. (Well… maybe not!) You can implement numerous rounding strategies in pure Python, and you have sharpened your skills on rounding NumPy arrays and Pandas `+Series+` and `+DataFrame+` objects.

There’s just one more step: knowing when to apply the right strategy.

=== Applications and Best Practices

The last stretch on your road to rounding virtuosity is understanding when to apply your newfound knowledge. In this section, you’ll learn some best practices to make sure you round your numbers the right way.

==== Store More and Round Late

When you deal with large sets of data, storage can be an issue. In most relational databases, each column in a table is designed to store a specific data type, and numeric data types are often assigned precision to help conserve memory.

For example, a temperature sensor may report the temperature in a long-running industrial oven every ten seconds accurate to eight decimal places. The readings from this are used to detect abnormal fluctuations in temperature that could indicate the failure of a heating element or some other component. So, there might be a Python script running that compares each incoming reading to the last to check for large fluctuations.

The readings from this sensor are also stored in a SQL database so that the daily average temperature inside the oven can be computed each day at midnight. The manufacturer of the heating element inside the oven recommends replacing the component whenever the daily average temperature drops `+.05+` degrees below normal.

For this calculation, you only need three decimal places of precision. But you know from the incident at the Vancouver Stock Exchange that removing too much precision can drastically affect your calculation.

If you have the space available, you should store the data at full precision. If storage is an issue, a good rule of thumb is to store at least two or three more decimal places of precision than you need for your calculation.

Finally, when you compute the daily average temperature, you should calculate it to the full precision available and round the final answer.

==== Obey Local Currency Regulations

When you order a cup of coffee for $2.40 at the coffee shop, the merchant typically adds a required tax. The amount of that tax depends a lot on where you are geographically, but for the sake of argument, let’s say it’s 6%. The tax to be added comes out to $0.144. Should you round this up to $0.15 or down to $0.14? The answer probably depends on the regulations set forth by the local government!

Situations like this can also arise when you are converting one currency to another. In 1999, the European Commission on Economical and Financial Affairs http://ec.europa.eu/economy_finance/publications/pages/publication1224_en.pdf[codified the use of the “rounding half away from zero” strategy] when converting currencies to the Euro, but other currencies may have adopted different regulations.

Another scenario, https://en.wikipedia.org/wiki/Cash_rounding[“Swedish rounding”], occurs when the minimum unit of currency at the accounting level in a country is smaller than the lowest unit of physical currency. For example, if a cup of coffee costs $2.54 after tax, but there are no 1-cent coins in circulation, what do you do? The buyer won’t have the exact amount, and the merchant can’t make exact change.

How situations like this are handled is typically determined by a country’s government. You can find a list of rounding methods used by various countries on https://en.wikipedia.org/wiki/Cash_rounding[Wikipedia].

If you are designing software for calculating currencies, you should always check the local laws and regulations in your users’ locations.

==== When In Doubt, Round Ties To Even

When you are rounding numbers in large datasets that are used in complex computations, the primary concern is limiting the growth of the error due to rounding.

Of all the methods we’ve discussed in this article, the “rounding half to even” strategy minimizes rounding bias the best. Fortunately, Python, NumPy, and Pandas all default to this strategy, so by using the built-in rounding functions you’re already well protected!

=== Summary

Whew! What a journey this has been!

In this article, you learned that:

* There are various rounding strategies, which you now know how to implement in pure Python.
* Every rounding strategy inherently introduces a rounding bias, and the “rounding half to even” strategy mitigates this bias well, most of the time.
* The way in which computers store floating-point numbers in memory naturally introduces a subtle rounding error, but you learned how to work around this with the `+decimal+` module in Python’s standard library.
* You can round NumPy arrays and Pandas `+Series+` and `+DataFrame+` objects.
* There are best practices for rounding with real-world data.

*__ Take the Quiz:* Test your knowledge with our interactive “Rounding Numbers in Python” quiz. Upon completion you will receive a score so you can track your learning progress over time:

link:/quizzes/python-rounding/[Take the Quiz »]

If you are interested in learning more and digging into the nitty-gritty details of everything we’ve covered, the links below should keep you busy for quite a while.

At the very least, if you’ve enjoyed this article and learned something new from it, pass it on to a friend or team member! Be sure to share your thoughts with us in the comments. We’d love to hear some of your own rounding-related battle stories!

Happy Pythoning!

=== Additional Resources

*Rounding strategies and bias:*

* https://en.wikipedia.org/wiki/Rounding[Rounding], Wikipedia
* https://zipcpu.com/dsp/2017/07/22/rounding.html[Rounding Numbers without Adding a Bias], from https://zipcpu.com[ZipCPU]

*Floating-point and decimal specifications:*

* https://en.wikipedia.org/wiki/IEEE_754[IEEE-754], Wikipedia
* http://speleotrove.com/decimal/decarith.html[IBM’s General Decimal Arithmetic Specification]

*Interesting Reads:*

* http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf[What Every Computer Scientist Should Know About Floating-Point Arithmetic], David Goldberg, ACM Computing Surveys, March 1991
* https://docs.python.org/3/tutorial/floatingpoint.html[Floating Point Arithmetic: Issues and Limitations], from https://python.org[python.org]
* http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html[Why Python’s Integer Division Floors], by Guido van Rossum