Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python precision in string formatting with float numbers

I don't understand why, by formatting a string containing a float value, the precision of this last one is not respected. Ie:

'%f' % 38.2551994324

returns:

'38.255199'

(4 signs lost!)

At the moment I solved specifying:

'%.10f' % 38.2551994324

which returns '38.2551994324' as expected… but should I really force manually how many decimal numbers I want? Is there a way to simply tell to python to keep all of them?! (what should I do for example if I don't know how many decimals my number has?)

like image 860
daveoncode Avatar asked Dec 14 '13 17:12

daveoncode


2 Answers

but should I really force manually how many decimal numbers I want? Yes.

And even with specifying 10 decimal digits, you are still not printing all of them. Floating point numbers don't have that kind of precision anyway, they are mostly approximations of decimal numbers (they are really binary fractions added up). Try this:

>>> format(38.2551994324, '.32f')
'38.25519943239999776096738060005009'

there are many more decimals there that you didn't even specify.

When formatting a floating point number (be it with '%f' % number, '{:f}'.format(number) or format(number, 'f')), a default number of decimal places is displayed. This is no different from when using str() (or '%s' % number, '{}'.format(number) or format(number), which essentially use str() under the hood), only the number of decimals included by default differs; Python versions prior to 3.2 use 12 digits for the whole number when using str().

If you expect your rational number calculations to work with a specific, precise number of digits, then don't use floating point numbers. Use the decimal.Decimal type instead:

  • Decimal “is based on a floating-point model which was designed with people in mind, and necessarily has a paramount guiding principle – computers must provide an arithmetic that works in the same way as the arithmetic that people learn at school.” – excerpt from the decimal arithmetic specification.

  • Decimal numbers can be represented exactly. In contrast, numbers like 1.1 and 2.2 do not have exact representations in binary floating point. End users typically would not expect 1.1 + 2.2 to display as 3.3000000000000003 as it does with binary floating point.

like image 113
Martijn Pieters Avatar answered Nov 08 '22 08:11

Martijn Pieters


I would use the modern str.format() method:

>>> '{}'.format(38.2551994324)
'38.2551994324'

The modulo method for string formatting is now deprecated as per PEP-3101

like image 45
K DawG Avatar answered Nov 08 '22 06:11

K DawG