2016-04-13 23 views
6

Mentre lavoravo con la precisione del galleggiante, mi sono imbattuto in un fatto strano. Perché python stampa solo la parte intera quando formattato con "%.f". Sono disposto a conoscere il meccanismo alla base di questoPrecisione float Python senza precisione intera dopo il punto decimale

>>> 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? 

Grazie in anticipo per la spiegazione :)

+1

Perché ' "% .F"' è la stessa di '" % .0f "'? – Selcuk

+1

Per lo stesso motivo per cui '1.0' è lo stesso di' 1.', probabilmente. – TigerhawkT3

+0

Questo comportamento sembra non definito. La precisione opzionale è [data come un ''.'' (punto) seguito dalla precisione] (https://docs.python.org/2/library/stdtypes.html # operazioni sulle stringhe di formattazione-). Analogamente, [la documentazione in formato mini-specificazione del formato] (https://docs.python.org/2/library/string.html#format-specification-mini-language) richiede un argomento per la precisione. Dato che 'int()' restituisce 0, sembra un valore predefinito ragionevole, ma un comportamento indefinito significa esattamente questo. – Chris

risposta

4

E 'stato in quel modo ever since % formatting was added back in 1993; se a . non è seguito da un numero decimale, quindi precision is taken as zero.

Questo è documentato, ma è coerente con printf che % formattazione di Python è ispirato:

(opzionale) . seguito da numero intero o *, o nessuno che specifica la precisione della conversione. Nel caso in cui venga utilizzato *, la precisione viene specificata da un argomento aggiuntivo di tipo int. Se il valore di questo argomento è negativo, viene ignorato. Se non viene utilizzato né un numero né *, la precisione viene considerata pari a zero.

È interessante notare che, un'altra funzionalità non documentata ispirato anche da printf è che è possibile utilizzare * come la precisione, come sopra:

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

la tua risposta mi sembra logica. Ma mi chiedo perché il formato della stringa suscita errori di valore come menzionato da srowland nella sua risposta? –

+2

@HiteshPaul 'string.format' è un'API successiva (introdotta in PEP 3101), quindi era possibile che fosse conforme alle specifiche; il comportamento non documentato di '%' non può essere rimosso senza interrompere la compatibilità con le versioni precedenti. – ecatmur

+0

@HiteshPaul Vedi la mia risposta qui sotto :) –

1

La documentazione per la precisione here non parlare di un default se la precisione è omesso. Posso solo supporre che funzioni in questo modo perché lo fa!

I documenti forniscono la precisione predefinita per un% f come 6 nella lingua mini di specifica del formato here. Forse specificando una precisione con il. e quindi omettendo un valore intero, l'interprete assume che dovrebbe essere zero?

Questo comportamento può persino comportarsi in modo diverso su diversi interpreti. Trova comunque interessante :).

È interessante notare che, utilizzando str.format lancia un bel ValueError nel mio 2.7 interprete:

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

Sembra strano, Python solleva ValueError per il formato stringa e nessuno per il formato '%'. –

+0

Completamente d'accordo con te :). Immagino che il formato abbia un'implementazione più rigorosa su questo punto. – srowland

+0

quindi vuol dire che l'implementazione interna differisce per il formato stringa e il formato%? –

1

L'operatore % ha il seguente comportamento, come si osserva:

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

Il parser passa attraverso la stringa di formato, con la precisione undefined (-1) by default. Quando colpisce il ., la precisione will be set to 0. Gli argomenti verranno passati allo helper function formatfloat che utilizza la precisione predefinita 6 se non viene fornita alcuna precisione e non viene utilizzato ..

Una nota interessante è che sarà effettivamente str.format()throw an exception in questo caso, probabilmente, per una più facile applicazione e non lasciare che le persone si basano sul comportamento non specificato:

>>> "{:.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