2016-04-13 7 views
6

Während ich mit Float-Präzision arbeitete, stolperte ich über eine seltsame Tatsache. Warum druckt Python nur den ganzzahligen Teil, wenn es mit "%.f" formatiert wird. Ich bin bereit, den Mechanismus hinter diesemPython Float-Genauigkeit ohne Ganzzahl Genauigkeit nach dem Komma

>>> a = float(2.12345) 
>>> a 
2.12345 
>>> print "%.2f" % a 
2.12 
>>> print "%.1f" % a 
2.1 
>>> print "%f" % a 
2.123450 
>>> print "%.f" % a 
2     #why? 

Vielen Dank im Voraus für die Erklärung wissen :)

+1

Da '„% .f“' ist das gleiche wie '“ % .0f "'? – Selcuk

+1

Aus dem gleichen Grund, dass "1.0" wahrscheinlich gleich "1." ist. – TigerhawkT3

+0

Dies scheint ein undefiniertes Verhalten zu sein. Die optionale Genauigkeit ist [angegeben als ''. '' (Punkt) gefolgt von der Genauigkeit] (https://docs.python.org/2/library/stdtypes.html # String-Formatierung-Operationen). Die [kleinformatige Dokumentation der Formatspezifikation] (https://docs.python.org/2/library/string.html#format-specification-mini-language) erfordert ebenfalls ein Argument für die Genauigkeit. Da 'int()' 0 zurückgibt, scheint es ein vernünftiger Standard zu sein, aber undefiniertes Verhalten bedeutet genau das. – Chris

Antwort

4

Es gewesen ist auf diese Weise ever since % formatting was added back in 1993; Wenn auf eine . keine Dezimalzahl folgt, dann precision is taken as zero.

Dies ist nicht dokumentiert, sondern steht im Einklang mit printf, die % Formatierung des Python wurde inspiriert von:

(optional) . gefolgt von Integer-Zahl oder * oder keines von beiden, die Genauigkeit der Umwandlung angibt. Wenn * verwendet wird, wird die Genauigkeit durch ein zusätzliches Argument vom Typ int angegeben. Wenn der Wert dieses Arguments negativ ist, wird es ignoriert. Wenn weder eine Zahl noch * verwendet wird, wird die Genauigkeit als Null angenommen.

Interessanterweise eine andere nicht dokumentierte Funktion auch durch printf inspiriert ist, dass Sie * als Präzision verwenden können, wie oben:

>>> "%6.*f" % (2, 1.234) 
' 1.23' 
+0

Ihre Antwort scheint mir logisch. Aber ich frage mich, warum das String-Format Wertfehler wie von srowland in seiner Antwort erwähnt erhöht? –

+2

@HiteshPaul 'string.format' ist eine spätere API (eingeführt in PEP 3101), so dass es möglich war, dass sie genau der Spezifikation entspricht; Das undokumentierte Verhalten von '%' konnte nicht entfernt werden, ohne die Abwärtskompatibilität zu beeinträchtigen. – ecatmur

+0

@HiteshPaul Siehe meine Antwort unten :) –

1

Die Dokumentation für Präzision here keinen Standard erwähnen, wenn die Präzision weggelassen wird. Ich kann nur annehmen, dass es nur so funktioniert, weil es funktioniert!

Die Dokumente geben die Standardpräzision für einen% f wie 6 in der Formatspezifikation Mini-Sprache here an. Vielleicht durch Angabe einer Genauigkeit mit dem. und dann, indem ein Integer-Wert weggelassen wird, nimmt der Interpreter an, dass es Null sein sollte?

Dies kann sich sogar bei verschiedenen Interpretern anders verhalten. Interessant finde ich sowieso :).

Interessanterweise str.format mit wirft einen schönen Valueerror in meinem 2.7-Interpreter:

>>> f = 234.12345676 
>>> "{:.f}".format(f) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
ValueError: Format specifier missing precision 
+0

Es scheint jedoch seltsam, Python löst ValueError für String-Format und keine für '%' Format. –

+0

stimme voll und ganz mit dir :). Ich denke, Format hat eine strengere Umsetzung in diesem Punkt. – srowland

+0

also bedeutet das, dass die interne Implementierung für String Format und% Format unterschiedlich ist? –

1

Der % Betreiber hat das folgende Verhalten, wie Sie beobachtet:

>>> "%.f" % 1.23 
'1' 

Der Parser durchläuft die Formatzeichenfolge mit der Genauigkeit undefined (-1) by default. Wenn es die . trifft, die Präzision will be set to 0. Die Argumente werden an die helper function formatfloat übergeben, die die Standardpräzision 6 verwendet, wenn keine Genauigkeit angegeben ist und keine . verwendet wird.

Eine interessante Anmerkung ist, dass str.format() tatsächlich throw an exception in diesem Fall wahrscheinlich für eine einfachere Implementierung und nicht lassen Menschen auf nicht näher bezeichnet Verhalten verlassen:

>>> "{:.f}".format(1.23) 
Traceback (most recent call last): 
    File "<ipython-input-6-677ba2e4a680>", line 1, in <module> 
    "{:.f}".format(1.23) 
ValueError: Format specifier missing precision 
Verwandte Themen