ticks - python plot beschriftung




Begrenzung auf zwei Dezimalstellen (13)

tldr;)

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

Unendlicher Test:

import random
for x in iter(random.random, None):           # verify FOREVER that rounding is fixed :-)
    assert float(repr(x)) == x                # Reversible repr() conversion
    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 the supermaket with Python 2.7+ :-)

Dokumente

Siehe Release Notes 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 Deserialisierung von Floats und komplexen Zahlen mit den Modulen marshal, pickle und json; Parsen von Float- und imaginären Literalen im Python-Code; und Dezimal-zu-Float-Konvertierung.

Im Zusammenhang damit gibt das repr () einer Fließkommazahl x nun ein Ergebnis basierend auf der kürzesten Dezimalzahl zurück, die bei korrekter Rundung (mit Rundungs-Halb-zu-Gerade-Rundungsmodus) garantiert wieder auf x gerundet wird. Zuvor gab es eine Zeichenkette basierend auf der Rundung von x bis 17 Dezimalziffern.

Das damit verbundene Problem

EDIT - mehr Info numpy.float64 Die Formatierung von float vor Python 2.7 war ähnlich wie die aktuelle numpy.float64 . Beide Typen verwenden dieselbe 64-Bit- IEEE-754- Doppelpräzision mit 52-Bit-Mantisa. Ein großer Unterschied ist, dass np.float64.__repr__ häufig mit einer zu hohen Dezimalzahl formatiert ist, so dass kein Bit verloren gehen kann, aber keine gültige IEEE 754 Nummer existiert zwischen 13.949999999999999 und 13.950000000000001, das Ergebnis ist nicht nett und die Konvertierung repr(float(number_as_string)) ist nicht reversibel. Auf der anderen Seite: float.__repr__ ist so formatiert, dass jede Ziffer wichtig ist, die Sequenz lückenlos und die Konvertierung reversibel ist. Ganz einfach: Wenn Sie vielleicht eine numpy.float64-Nummer haben, konvertieren Sie sie in normal float, um für Menschen formatiert zu werden, nicht für numerische Prozessoren, sonst ist mit Python 2.7+ nichts mehr nötig.

Ich möchte a auf 13,95 gerundet werden.

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

Die round funktioniert nicht so, wie ich es erwartet habe.


Bei Python <3 (zB 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 prefered

Für weitere Informationen zu Option zwei empfehle ich diesen Link zur Formatierung von Zeichenfolgen aus den Python-Dokumenten .

Und für weitere Informationen zu Option eins genügt dieser Link und hat Infos zu den verschiedenen Flags.

Referenz: Konvertieren Sie die Fließkommazahl in eine bestimmte Genauigkeit und kopieren Sie sie anschließend in den String


Das Python-Tutorial hat einen Anhang mit dem Namen: Fließkomma-Arithmetik: Probleme und Einschränkungen . Lies es. Es erklärt, was passiert und warum Python sein Bestes gibt. Es hat sogar ein Beispiel, das Ihrem entspricht. Lassen Sie mich ein wenig zitieren:

>>> 0.1
0.10000000000000001

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

>>> round(0.1, 1)
0.10000000000000001

Das Problem ist, dass der für “0.1” gespeicherte binäre Gleitkommawert bereits die bestmögliche binäre Annäherung an 1/10 , also kann es nicht besser werden, ihn zu runden: es war schon so gut wie es geht.

Eine weitere Konsequenz ist, dass, da 0.1 nicht genau 1/10 , die Summierung von zehn Werten von 0.1 nicht genau 1.0 , entweder:

>>> 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 decimal .


Die Methode, die ich verwende, ist die des String-Slicing. Es ist relativ schnell und einfach.

Konvertieren Sie zuerst den Float in einen String, wählen Sie die Länge, die Sie möchten.

float = str(float)[:5]

In der obigen Zeile haben wir den Wert in eine Zeichenkette konvertiert und die Zeichenkette nur auf die ersten vier Ziffern oder Zeichen (inklusive) gesetzt.

Ich hoffe, das hilft!


Es gibt neue Formatspezifikationen, String Format Specification Mini-Language :

Sie können dasselbe tun wie:

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

Beachten Sie, dass das obige eine Zeichenfolge zurückgibt. um als float zu erhalten, einfach mit float(...)

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

Beachten Sie, dass das Umbrechen mit float() nichts ändert:

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

Es macht genau das, was Sie ihm gesagt haben, und es funktioniert richtig. Lesen Sie mehr über Fließkommaverwechslung und versuchen Sie vielleicht stattdessen, decimal verwenden.


Niemand scheint es bisher erwähnt zu haben, also lassen Sie mich ein Beispiel in Python 3.6's f-string / template-string Format geben, was ich sehr schön finde:

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

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

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

Python 2.7,

Hoffe, das wird helfen

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

Um eine Zahl auf eine Auflösung zu runden, ist der beste Weg der folgende, der mit jeder Auflösung arbeiten kann (0,01 für 2 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

Versuche die Codes unten:

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

Wie @Matt herausstellte, stellt Python 3.6 f-Strings zur Verfügung und sie können auch verschachtelte Parameter verwenden :

value = 2.34558
precision = 2
width = 4

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

Das result: 2.35 wird angezeigt result: 2.35


Zur Behebung des Gleitkommas in dynamischen 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)
#result in 6 precision -> Decimal('0.142857')
getcontext().prec = 28
Decimal(1) / Decimal(7)
#result in 28 precision -> Decimal('0.1428571428571428571428571429')

orig_float = 232569 / 16000.0

14.5355625

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

14.54





precision