Das Begrenzen von Gleitkommazahlen auf zwei Dezimalstellen


1691

Ich möchte aauf 13,95 gerundet werden .

>>> a
13.949999999999999
>>> round(a, 2)
13.949999999999999

Die roundFunktion funktioniert nicht wie erwartet.



6
Hmm ... Versuchen Sie, die Währung darzustellen? Wenn ja, sollten Sie keine Floats für Dollars verwenden. Sie könnten wahrscheinlich Floats für Pennys verwenden oder was auch immer die kleinste gemeinsame Währungseinheit ist, die Sie modellieren möchten, aber die beste Vorgehensweise ist die Verwendung einer Dezimaldarstellung, wie HUAGHAGUAH in seiner Antwort vorgeschlagen hat.
SingleNegationElimination

63
Es ist wichtig, die Währung nicht im Float darzustellen. Schwimmer sind nicht präzise. Aber Penny- oder Centbeträge sind ganze Zahlen. Ganzzahlen sind daher die richtige Darstellung der Währung.
Davoud Taghawi-Nejad

2
@ DavoudTaghawi-Nejad oder mehr auf den Punkt ... Der Dezimaltyp
Basic

17
Ich komme wahrscheinlich zu spät hierher, aber ich wollte fragen, haben die Entwickler von Python dieses Problem gelöst? Denn wenn ich runde mache (13.949999999999999, 2), bekomme ich einfach 13.95. Ich habe es in Python 2.7.6 sowie 3.4 versucht. Es klappt. Sie sind sich nicht sicher, ob es 2009 überhaupt 2.7 gab? Vielleicht ist es eine Python 2.5-Sache?
bad_keypoints

Antworten:


1690

Sie stoßen auf das alte Problem mit Gleitkommazahlen, bei denen nicht alle Zahlen exakt dargestellt werden können. Die Befehlszeile zeigt Ihnen nur die vollständige Gleitkommaform aus dem Speicher.

Bei der Gleitkommadarstellung ist Ihre gerundete Version dieselbe Zahl. Da Computer binär sind, speichern sie Gleitkommazahlen als Ganzzahl und teilen sie dann durch eine Zweierpotenz, sodass 13,95 auf ähnliche Weise wie 125650429603636838 / (2 ** 53) dargestellt werden.

Zahlen mit doppelter Genauigkeit haben eine Genauigkeit von 53 Bit (16 Stellen) und reguläre Gleitkommazahlen eine Genauigkeit von 24 Bit (8 Stellen). Der Gleitkommatyp in Python verwendet die doppelte Genauigkeit , um die Werte zu speichern.

Zum Beispiel,

>>> 125650429603636838/(2**53)
13.949999999999999

>>> 234042163/(2**24)
13.949999988079071

>>> a = 13.946
>>> print(a)
13.946
>>> print("%.2f" % a)
13.95
>>> round(a,2)
13.949999999999999
>>> print("%.2f" % round(a, 2))
13.95
>>> print("{:.2f}".format(a))
13.95
>>> print("{:.2f}".format(round(a, 2)))
13.95
>>> print("{:.15f}".format(round(a, 2)))
13.949999999999999

Wenn Sie nur zwei Dezimalstellen benötigen (um beispielsweise einen Währungswert anzuzeigen), haben Sie einige bessere Möglichkeiten:

  1. Verwenden Sie Ganzzahlen und speichern Sie Werte in Cent, nicht in Dollar, und dividieren Sie diese durch 100, um sie in Dollar umzurechnen.
  2. Oder verwenden Sie eine Festkommazahl wie eine Dezimalzahl .

27
@Christian Es gibt einen grundlegenden Unterschied zwischen dem gespeicherten Wert und der Anzeige dieses Werts. Das Formatieren der Ausgabe sollte es Ihnen ermöglichen, nach Bedarf Auffüllungen sowie Komma-Trennzeichen usw. hinzuzufügen.
Basic

22
Erwähnenswert ist, dass "%.2f" % round(a,2)Sie nicht nur in printf, sondern auch in solchen Dingen wiestr()
andilabs

20
Warum nehmen die Leute beim Gleitkomma-Runden immer die Währung an? Manchmal möchten Sie nur mit weniger Präzision arbeiten.
worc

9
@radtek: Sie müssen verstehen, dass der Binärwert (vom Typ float) nur die nächste verfügbare Annäherung an die Dezimalzahl ist (die Sie als Mensch kennen). Es gibt keinen solchen (endlich darstellbaren) Binärwert wie 0,245. Es existiert einfach nicht und kann mathematisch nicht existieren. Der Binärwert, der 0,245 am nächsten kommt, ist etwas kleiner als 0,245, daher rundet er natürlich ab. Ebenso gibt es keine 0,225 in Binärform, aber der Binärwert, der 0,225 am nächsten kommt, ist etwas größer als 0,225, also rundet er natürlich auf.
John Y

12
@radtek: Du hast buchstäblich um eine Erklärung gebeten. Die einfachste Lösung ist in der Tat die Verwendung Decimal, und dies war eine der in dieser Antwort vorgestellten Lösungen. Die andere bestand darin, Ihre Mengen in Ganzzahlen umzuwandeln und Ganzzahlarithmetik zu verwenden. Beide Ansätze tauchten auch in anderen Antworten und Kommentaren auf.
John Y

586

Es gibt neue Formatspezifikationen, String-Formatspezifikation Mini-Sprache :

Sie können das Gleiche tun wie:

"{:.2f}".format(13.949999999999999)

Hinweis 1: Das obige gibt eine Zeichenfolge zurück. Um als Float zu erhalten, wickeln Sie einfach mit float(...):

float("{:.2f}".format(13.949999999999999))

Anmerkung 2: Das Umwickeln mit float()ändert nichts:

>>> x = 13.949999999999999999
>>> x
13.95
>>> g = float("{:.2f}".format(x))
>>> g
13.95
>>> x == g
True
>>> h = round(x, 2)
>>> h
13.95
>>> x == h
True

17
Um auch Kommas hinzuzufügen, können Sie '{0:,.2f}'.format(1333.949999999)welche drucken '1,333.95'.
Stephen Blum

@ OnurYıldırım: ja, aber du kannst es mit einwickeln float(); float("{0:.2f}".format(13.9499999))
Jossef Harush

5
@ JossefHarush Sie können es mit float () einwickeln, aber Sie haben nichts gewonnen. Jetzt haben Sie wieder einen Schwimmer mit der gleichen Ungenauigkeit. 13.9499999999999 und 13.95 sind die gleichen Float.
Ned Batchelder

4
@NedBatchelder: Ich stimme zu, dass sie gleich sind, aber dies begrenzt den
Gleitkommawert

8
Übrigens, seit Python 3.6 können wir F-Strings verwenden:f"Result is {result:.2f}"
Andrey Semakin

289

Die integrierte Funktion round()funktioniert in Python 2.7 oder höher einwandfrei.

Beispiel:

>>> round(14.22222223, 2)
14.22

Lesen Sie die Dokumentation .


1
Soll ich also verstehen, dass dies ein Python 2.7-Fehler ist? Warum würde eine solche Grundfunktion unterschiedliche Ergebnisse von v 2.7 bis v 3 liefern?
MikeM

aber round(2.16, 1)geben , 2.2warum Python nur bieten truncatefunc
jiamo

Wenn Sie beispielsweise versuchen, den Wert 2.675 auf zwei Dezimalstellen zu runden, erhalten Sie diese >>> round(2.675, 2) 2.67 docs.python.org/2/tutorial/floatingpoint.html
gefahr89

4
Von der Python 3-Dokumentationsseite:Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float.
Richard Dally

Beachten Sie, dass beim Versuch, mit dieser Methode eine Zahl wie 1.00000 auszudrucken, nur 1.0 ausgedruckt wird, unabhängig davon, wie viele Dezimalstellen Sie angeben.
Josh Correia

142

Ich bin der Meinung, dass der einfachste Ansatz darin besteht, die format()Funktion zu verwenden.

Zum Beispiel:

a = 13.949999999999999
format(a, '.2f')

13.95

Dies erzeugt eine Gleitkommazahl als Zeichenfolge, die auf zwei Dezimalstellen gerundet ist.


97

Verwenden

print"{:.2f}".format(a)

anstatt

print"{0:.2f}".format(a)

Weil letzteres zu Ausgabefehlern führen kann, wenn versucht wird, mehrere Variablen auszugeben (siehe Kommentare).


2
Das ist Unsinn. Die beiden angegebenen Anweisungen verhalten sich in Python 2.7 identisch, und nur die zweite Anweisung ist in Python 2.6 gültig. (Keine der Anweisungen ist in Python 3 oder Python <2.6 gültig.) Die erste Form hat außer der Kürze keinen Vorteil.
Mark Dickinson

1
Ich meine, das Drucken des Formats "{0: .2f} {0: .2f}" (a, b) führt zu einem Fehler bei der Ausgabe - es gibt zweimal den Wert 'a' aus. Während des Druckvorgangs "{:. 2f} {: .2f}" gibt das Format (a, b) die Werte 'a' und 'b' aus.
Alexey Antonenko

2
Für Python 3 müssen Sie nur Klammern print (...) hinzufügen. Und in ihnen ist alles, was ich geschrieben habe, richtig.
Alexey Antonenko

"Ich meine, print" {0: .2f} {0: .2f} ". Format (a, b) führt zu Fehlern bei der Ausgabe". Ah. Nun, das ist eine ganz andere Aussage! Vielleicht sollten Sie Ihre Antwort bearbeiten? (Was bedeutet "Fehler auslösen" beispielsweise in der aktuellen Antwort? Können Sie ein Beispiel für einen Fall geben, in dem die zweite Aussage eine Ausnahme auslöst, die erste jedoch nicht?)
Mark Dickinson

3
Sie würden nach dem Drucken ("{0: .2f} {1: .2f}". Format (a, b)) sein, wenn Sie zwei Variablen haben
Hovo

95

Die meisten Zahlen können in Floats nicht genau dargestellt werden. Wenn Sie die Zahl runden möchten, weil dies für Ihre mathematische Formel oder Ihren Algorithmus erforderlich ist, möchten Sie runden verwenden. Wenn Sie die Anzeige nur auf eine bestimmte Genauigkeit beschränken möchten, verwenden Sie nicht einmal rund und formatieren Sie sie einfach als diese Zeichenfolge. (Wenn Sie es mit einer alternativen Rundungsmethode anzeigen möchten und es Tonnen gibt, müssen Sie die beiden Ansätze mischen.)

>>> "%.2f" % 3.14159
'3.14'
>>> "%.2f" % 13.9499999
'13.95'

Und schließlich, wenn auch am wichtigsten, wenn Sie genaue Mathematik wollen, dann wollen Sie überhaupt keine Floats. Das übliche Beispiel ist der Umgang mit Geld und das Speichern von 'Cent' als Ganzzahl.


68

Versuchen Sie den folgenden Code:

>>> a = 0.99334
>>> a = int((a * 100) + 0.5) / 100.0 # Adding 0.5 rounds it up
>>> print a
0.99

Aber seien Sie gewarnt, der Wert von a ist immer noch ein ungenauer Float. Schauen Sie hier - repl.it/LJs (Klicken Sie oben rechts auf "Sitzung ausführen ").
Lebensbalance

3
Wenn Sie sich für diesen Ansatz entscheiden, sollten Sie für eine genauere Darstellung eine 0,5 hinzufügen. int (a * 100 + 0,5) / 100,0; Die Verwendung von math.ceil ist eine weitere Option.
Arhuaco

3
@ShashankSawant: Nun, zum einen rundet sich die vorgestellte Antwort nicht ab, sie schneidet ab. Der Vorschlag, am Ende die Hälfte hinzuzufügen, wird abgerundet, aber es hat keinen Vorteil, dies zu tun, anstatt nur die roundFunktion zu verwenden. Zum anderen bleibt das ursprüngliche Problem des OP bestehen, da diese Lösung immer noch Gleitkomma verwendet, selbst für die "korrigierte" Version dieser "Lösung".
John Y

3
-1, dies ist nur eine unnötige Neuimplementierung der roundFunktion (die in der Frage verwendet wurde).
Zwischenzeit

4
@interjay was notwendig ist wenn das round()nicht wie das erwähnte OP funktioniert.
Pithikos

57

TLDR;)

Das Rundungsproblem der Eingabe / Ausgabe wurde durch Python 2.7.0 und 3.1 endgültig gelöst .

Eine korrekt gerundete Zahl kann reversibel hin und her konvertiert werden:
str -> float() -> repr() -> float() ...oder Decimal -> float -> str -> Decimal
Ein Dezimaltyp ist für die Speicherung nicht mehr erforderlich.


(Natürlich kann es erforderlich sein, ein Ergebnis der Addition oder Subtraktion gerundeter Zahlen zu runden, um die akkumulierten Fehler des letzten Bits zu beseitigen. Eine explizite Dezimalarithmetik kann immer noch praktisch sein, aber eine Konvertierung in eine Zeichenfolge durch str()(dh mit Rundung auf 12 gültige Ziffern) ) ist normalerweise gut genug, wenn keine extreme Genauigkeit oder keine extreme Anzahl aufeinanderfolgender arithmetischer Operationen erforderlich ist.)

Unendlicher Test :

import random
from decimal import Decimal
for x in iter(random.random, None):           # Verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion.
    assert float(Decimal(repr(x))) == x
    assert len(repr(round(x, 10))) <= 12      # Smart decimal places in repr() after round.
    if x >= 0.1:                              # Implicit rounding to 12 significant digits
        assert str(x) == repr(round(x, 12))   # by str() is good enough for small errors.
        y = 1000 * x                             # Decimal type is excessive for shopping
        assert str(y) == repr(round(y, 12 - 3))  # in a supermaket with Python 2.7+ :-)

Dokumentation

Siehe die Versionshinweise Python 2.7 - Andere Sprachänderungen im vierten Absatz:

Konvertierungen zwischen Gleitkommazahlen und Zeichenfolgen werden jetzt auf den meisten Plattformen korrekt gerundet . Diese Konvertierungen finden an vielen verschiedenen Stellen statt: str () auf Floats und komplexen Zahlen; die Float- und komplexen Konstruktoren; numerische Formatierung; Serialisierung und De-Serialisierung Schwimmer und komplexe Zahlen mit der marshal, pickleund jsonModule; Parsen von Float- und imaginären Literalen in Python-Code; und Umwandlung von Dezimal in Gleitkomma.

In diesem Zusammenhang gibt die repr () einer Gleitkommazahl x jetzt ein Ergebnis zurück, das auf der kürzesten Dezimalzeichenfolge basiert, die bei korrekter Rundung (mit Rundungshalb-zu-Gerade-Rundungsmodus) garantiert auf x zurückrundet. Zuvor wurde eine Zeichenfolge basierend auf der Rundung von x auf 17 Dezimalstellen angegeben.

Das damit verbundene Problem


Weitere Informationen: Die Formatierung floatvor Python 2.7 war ähnlich der aktuellen numpy.float64. Beide Typen verwenden dieselbe 64-Bit- IEEE 754- Doppelgenauigkeit mit 52-Bit-Mantisse. Ein großer Unterschied besteht darin, dass np.float64.__repr__häufig mit einer übermäßigen Dezimalzahl formatiert wird, sodass kein Bit verloren gehen kann, aber zwischen 13.949999999999999 und 13.950000000000001 keine gültige IEEE 754-Nummer vorhanden ist. Das Ergebnis ist nicht schön und die Konvertierung repr(float(number_as_string))ist mit numpy nicht umkehrbar. Auf der anderen Seite:float.__repr__ist so formatiert, dass jede Ziffer wichtig ist; Die Reihenfolge ist lückenlos und die Konvertierung ist reversibel. Einfach: Wenn Sie möglicherweise eine numpy.float64-Nummer haben, konvertieren Sie diese in normales float, um sie für Menschen und nicht für numerische Prozessoren zu formatieren. Andernfalls ist mit Python 2.7+ nichts mehr erforderlich.


Warum herabgestimmt? Die Frage betraf Python float(doppelte Genauigkeit) und normal round, nicht numpy.double und seine Konvertierung in einen String. Eine einfache Python-Rundung kann wirklich nicht besser durchgeführt werden als in Python 2.7. Die meisten Antworten wurden vor 2.7 geschrieben, sind jedoch veraltet, obwohl sie ursprünglich sehr gut waren. Dies ist der Grund meiner Antwort.
Hynekcer

53 Bits, wenn Sie das "versteckte Bit" einschließen, was implizit ist 1, außer während des "allmählichen Unterlaufs".
Rick James

Es ist nicht Round's Fehler, es ist der Anzeigefehler.
Rick James

Ja, es ist bekannt. Ich vermisse jedoch einen Kontext, wenn Sie etwas in Python 2.7 Versionshinweisen oder in meinem Text oder gar nichts ablehnen. Der Zweck dieser Frage ist komplizierter als nötig. Es sollte hinzugefügt werden, dass auch die Konvertierung von String zu Float in Python 2.7 aufgrund eines Rundungsfehlers auf bestimmten 32-Bit-Intel-Chips behoben wurde und dass "die round () - Funktion jetzt auch korrekt gerundet ist." ( Versionshinweise - 3.1-Funktionen wurden auf 2.7 zurückportiert ). Kannst du zustimmen?
Hynekcer

1
Hoppla, das war a*bvs b*a. Danke für die Links - Nostalgie.
Rick James

52

Bei Python <3 (z. B. 2.6 oder 2.7) gibt es zwei Möglichkeiten.

# Option one 
older_method_string = "%.9f" % numvar

# Option two (note ':' before the '.9f')
newer_method_string = "{:.9f}".format(numvar)

Beachten Sie jedoch, dass für Python-Versionen über 3 (z. B. 3.2 oder 3.3) Option zwei bevorzugt wird .

Für weitere Informationen zu Option 2 empfehle ich diesen Link zur Formatierung von Zeichenfolgen aus der Python-Dokumentation .

Für weitere Informationen zu Option 1 reicht dieser Link aus und enthält Informationen zu den verschiedenen Flags .

Referenz: Konvertieren Sie die Gleitkommazahl in eine bestimmte Genauigkeit und kopieren Sie sie in eine Zeichenfolge


Wie repräsentieren Sie eine ganze Zahl? Wenn ich das Format "{i3}" (numvar) verwende, wird eine Fehlermeldung angezeigt.
Skytux

Das meine ich: Wenn numvar=12.456, dann "{:.2f}".format(numvar)ergibt sich 12.46aber "{:2i}".format(numvar)ein Fehler und ich erwarte 12.
Skytux

50

Sie können das Ausgabeformat ändern:

>>> a = 13.95
>>> a
13.949999999999999
>>> print "%.2f" % a
13.95

47

Niemand hier scheint es bisher erwähnt zu haben, also lassen Sie mich ein Beispiel im F-String / Template-String-Format von Python 3.6 geben, das ich für sehr ordentlich halte:

>>> f'{a:.2f}'

Es funktioniert auch gut mit längeren Beispielen, mit Operatoren und ohne Parens:

>>> print(f'Completed in {time.time() - start:.2f}s')

39

Sie können den Formatoperator verwenden , um den Wert in Python auf 2 Dezimalstellen zu runden:

print(format(14.4499923, '.2f')) // output is 14.45

4
Dies gibt Zeichenfolge zurück
Jemshit Iskenderov

29

In Python 2.7:

a = 13.949999999999999
output = float("%0.2f"%a)
print output

1
Das hilft überhaupt nicht. outputhat genau den gleichen Wert wie a, so dass Sie genauso gut print aanstelle print outputder letzten Zeile geschrieben haben könnten .
Mark Dickinson

@ MarkDickinson Könnten Sie es bitte noch einmal versuchen. Weil es in meinem Compiler wie erwartet läuft.
Shashank Singh

1
Du vermisst meinen Standpunkt. Ja, Ihr Code wird gedruckt 13.95. Aber so tut print a, für diesen bestimmten Wert a, in Python 2.7, so ist es nicht wirklich klar , was der Punkt des Formatierungsschrittes war.
Mark Dickinson

@ MarkDickinson Ich habe den Code bearbeitet. Ich bin damit einverstanden, dass 'print a' den gleichen Wert wie "print output" druckt. Wenn Sie jedoch "a == output" vergleichen, ist das Ergebnis "False", da der Formatierungsschritt den Gleitkommawert "a" auf zwei Dezimalstellen abrundet.
Shashank Singh

1
Haben Sie tatsächlich versucht, a == outputden Code anzuzeigen, den Sie anzeigen? Es gibt Truefür mich und ich vermute, dass es auch für Sie tut.
Mark Dickinson

22

Das Python-Tutorial enthält einen Anhang mit dem Namen Gleitkomma-Arithmetik: Probleme und Einschränkungen . Lies es. Es erklärt, was passiert und warum Python sein Bestes gibt. Es gibt sogar ein Beispiel, das zu Ihrem passt. Lassen Sie mich ein bisschen zitieren:

>>> 0.1
0.10000000000000001

Sie könnten versucht sein, die round() Funktion zu verwenden, um sie auf die erwartete einzelne Ziffer zurückzuschneiden. Das macht aber keinen Unterschied:

>>> round(0.1, 1)
0.10000000000000001

Das Problem ist, dass der für gespeicherte binäre Gleitkommawert “0.1” bereits die bestmögliche binäre Annäherung an 1/10war. Ein erneuter Rundungsversuch kann ihn also nicht verbessern: Er war bereits so gut wie es nur geht.

Eine andere Konsequenz ist, dass, da dies 0.1 nicht genau ist 1/10, die Summierung von zehn Werten von 0.1möglicherweise auch nicht genau ergibt 1.0:

>>> sum = 0.0
>>> for i in range(10):
...     sum += 0.1
...
>>> sum
0.99999999999999989

Eine Alternative und Lösung für Ihre Probleme wäre die Verwendung des decimalModuls.


18

Wie @Matt hervorhob, bietet Python 3.6 F-Strings und sie können auch verschachtelte Parameter verwenden :

value = 2.34558
precision = 2
width = 4

print(f'result: {value:{width}.{precision}f}')

welches angezeigt wird result: 2.35



11

Verwenden Sie eine Kombination aus Dezimalobjekt und round () -Methode.

Python 3.7.3
>>> from decimal import Decimal
>>> d1 = Decimal (13.949999999999999) # define a Decimal
>>> d1 
Decimal('13.949999999999999289457264239899814128875732421875')
>>> d2 = round(d1, 2) # round to 2 decimals
>>> d2
Decimal('13.95')

7

Zum Fixieren des Gleitkommas in typdynamischen Sprachen wie Python und JavaScript verwende ich diese Technik

# For example:
a = 70000
b = 0.14
c = a * b

print c # Prints 980.0000000002
# Try to fix
c = int(c * 10000)/100000
print c # Prints 980

Sie können Decimal auch wie folgt verwenden:

from decimal import *
getcontext().prec = 6
Decimal(1) / Decimal(7)
# Results in 6 precision -> Decimal('0.142857')

getcontext().prec = 28
Decimal(1) / Decimal(7)
# Results in 28 precision -> Decimal('0.1428571428571428571428571429')

1
getcontext().prec = 6funktioniert nur für den Funktionsumfang oder für alle Orte?
Julio Marins

1
Kontexte sind Umgebungen für arithmetische Operationen. Sie regeln die Genauigkeit, legen Regeln für die Rundung fest, bestimmen, welche Signale als Ausnahmen behandelt werden, und begrenzen den Bereich für Exponenten. Jeder Thread hat seinen eigenen aktuellen Kontext @JulioMarins
Siamand

7
from decimal import Decimal


def round_float(v, ndigits=2, rt_str=False):
    d = Decimal(v)
    v_str = ("{0:.%sf}" % ndigits).format(round(d, ndigits))
    if rt_str:
        return v_str
    return Decimal(v_str)

Ergebnisse:

Python 3.6.1 (default, Dec 11 2018, 17:41:10)
>>> round_float(3.1415926)
Decimal('3.14')
>>> round_float(3.1445926)
Decimal('3.14')
>>> round_float(3.1455926)
Decimal('3.15')
>>> round_float(3.1455926, rt_str=True)
'3.15'
>>> str(round_float(3.1455926))
'3.15'

6
orig_float = 232569 / 16000.0

14.5355625

short_float = float("{:.2f}".format(orig_float)) 

14.54


5

Was ist mit einer Lambda-Funktion wie dieser:

arred = lambda x,n : x*(10**n)//1/(10**n)

Auf diese Weise können Sie einfach Folgendes tun:

arred(3.141591657,2)

und bekomme

3.14

4

Es ist einfach wie 1,2,3:

  1. Verwenden Sie das Dezimalmodul für eine schnelle, korrekt gerundete Dezimal-Gleitkomma-Arithmetik:

    d = Dezimal (10000000.0000009)

Rundung erreichen:

   d.quantize(Decimal('0.01'))

wird Ergebnisse mit Decimal('10000000.00')

  1. oben machen TROCKEN:
    def round_decimal(number, exponent='0.01'):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(exponent))

ODER

    def round_decimal(number, decimal_places=2):
        decimal_value = Decimal(number)
        return decimal_value.quantize(Decimal(10) ** -decimal_places)
  1. stimme dieser Antwort zu :)

PS: Kritik an anderen: Formatierung ist keine Rundung.


2

Um eine Zahl auf eine Auflösung zu runden, ist der folgende Weg der beste, der mit jeder Auflösung funktionieren kann (0,01 für zwei Dezimalstellen oder sogar andere Schritte):

>>> import numpy as np
>>> value = 13.949999999999999
>>> resolution = 0.01
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
13.95

>>> resolution = 0.5
>>> newValue = int(np.round(value/resolution))*resolution
>>> print newValue
14.0

funktioniert bei mir nicht unter python 3.4.3 und numpy 1.9.1? >>> importiere numpy als np >>> res = 0.01 >>> value = 0.184 >>> np.round (value / res) * res 0.17999999999999999
szeitlin

1
Auf der Suche nach Dokumentation sehe ich, dass das Problem von numpy.roundGenauigkeit / Präzision herrührt. Daher muss es vor der Multiplikation mit der Auflösung als int definiert werden. Ich habe den Code aktualisiert. Danke für das!
Iblasi

Das einzige, was notwendig ist, ist das numpy.float64Ergebnis von np.round in zu konvertieren floatoder einfach zu verwenden round(value, 2). Zwischen 13.949999999999999 (= 1395/100) und 3.950000000000001 (= 1395 * .01) existiert keine gültige IEEE 754-Nummer. Warum denkst du, dass deine Methode die beste ist? Der ursprüngliche Wert 13.949999999999999289 (= Wert = rund (Wert, 2)) ist noch genauer als Ihr 13.95000000000000178 (gedruckt von np.float96). Weitere Informationen auch für numpy wurden jetzt zu meiner Antwort hinzugefügt, die Sie wahrscheinlich versehentlich abgelehnt haben. Es ging ursprünglich nicht um Numpy.
Hynekcer

@hynekcer Ich denke nicht, dass meine Antwort die beste ist. Ich wollte nur ein Beispiel für Limit Float zu n Dezimalstellen hinzufügen, aber das nächste einer definierten Auflösung. Ich habe wie gesagt überprüft, dass anstelle von intIhnen auch floatfür @szeitlin Beispiel verwendet werden kann. Vielen Dank für Ihren zusätzlichen Kommentar. (Sorry, aber ich habe dich nicht abgelehnt)
iblasi

Das Hinzufügen einer völlig neuen Abhängigkeit für die numerische Verarbeitung (Pandas) ist der "beste Weg"?
Hejazzman

1

lambda x, n: int (x * 10 n + .5) / 10 n arbeitet seit vielen Jahren in vielen Sprachen für mich .


-13

Die Methode, die ich benutze, ist das Schneiden von Strings. Es ist relativ schnell und einfach.

Konvertieren Sie zuerst den Float in eine Zeichenfolge und wählen Sie die gewünschte Länge aus.

float = str(float)[:5]

In der obigen einzelnen Zeile haben wir den Wert in eine Zeichenfolge konvertiert und die Zeichenfolge dann nur auf die ersten vier Ziffern oder Zeichen (einschließlich) beschränkt.

Ich hoffe, das hilft!


2
Bitte posten Sie keine identischen Antworten auf mehrere Fragen.
Vaultah

18
WOW ... tdh ... Bitte machen Sie niemals eine Buchhaltungssoftware ... Was passiert, wenn die Zahl zufällig 113,94 ist? Dies würde dazu führen, dass 113,9 ... 0,04 fehlen .... Auch dies hat bereits Antworten von vor über 5 Jahren ....
Angry 84
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.