Reputation: 1852
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 :)
Upvotes: 6
Views: 5678
Reputation: 15537
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
Upvotes: 1
Reputation: 157334
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'
Upvotes: 4
Reputation: 1705
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
Upvotes: 1