简体   繁体   中英

Python float precision with no integer precision after decimal point

While working with float precision, I stumbled across a strange fact. Why does python prints only the integer part when formatted with "%.f" . I am willing to know the mechanism behind this

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

Thanks in advance for the explanation :)

It's been that way ever since % formatting was added back in 1993 ; if a . is not followed by a decimal number then precision is taken as zero .

This is undocumented, but is consistent with printf , which Python's % formatting was inspired by:

(optional) . followed by integer number or * , or neither that specifies precision of the conversion. In the case when * is used, the precision is specified by an additional argument of type int. If the value of this argument is negative, it is ignored. If neither a number nor * is used, the precision is taken as zero.

Interestingly, another undocumented feature also inspired by printf is that you can use * as precision, as above:

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

The docs for precision here don't mention a default if the precision is ommitted. I can only assume it just works this way because it does!

The docs give the default precision for a %f as 6 in the format specification mini language here . Maybe by specifying a precision with the . and then by omitting an integer value, the interpreter assumes it should be zero?

This may even behave differently on different interpreters. Interesting find anyway :).

Interestingly, using str.format throws a nice ValueError in my 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

The % operator has the following behavior, like you observed:

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

The parser goes through the format string, with the precision being undefined ( -1 ) by default . When it hits the . , the precision will be set to 0 . The arguments will be passed to the helper function formatfloat which uses the default precision 6 if no precision is given, and no . is used.

An interesting note is that str.format() will actually throw an exception in this case, probably for easier implementation and not letting people rely on unspecified behavior:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM