45

I need to print or convert a float number to 15 decimal place string even if the result has many trailing 0s eg:

1.6 becomes 1.6000000000000000

I tried round(6.2,15) but it returns 6.2000000000000002 adding a rounding error

I also saw various people online who put the float into a string and then added trailing 0's manually but that seems bad...

What is the best way to do this?

ruohola
  • 16,015
  • 6
  • 33
  • 67
jonathan topf
  • 6,925
  • 12
  • 50
  • 77
  • 4
    Side note, but that last 2 is not a rounding error exactly. The number 6.2, like many other real numbers, is not exactly representable with a floating point variable in a computer. See http://docs.python.org/tutorial/floatingpoint.html and http://stackoverflow.com/questions/1089018/why-cant-decimal-numbers-be-represented-exactly-in-binary for more information. – mtrw Dec 19 '11 at 22:21
  • 3
    @mtrw, I think you could get away with calling it a rounding error - the input is being rounded to the closest binary number. – Mark Ransom Dec 19 '11 at 22:42

4 Answers4

75

For Python versions in 2.6+ and 3.x

You can use the str.format method. Examples:

>>> print('{0:.16f}'.format(1.6))
1.6000000000000001

>>> print('{0:.15f}'.format(1.6))
1.600000000000000

Note the 1 at the end of the first example is rounding error; it happens because exact representation of the decimal number 1.6 requires an infinite number binary digits. Since floating-point numbers have a finite number of bits, the number is rounded to a nearby, but not equal, value.

For Python versions prior to 2.6 (at least back to 2.0)

You can use the "modulo-formatting" syntax (this works for Python 2.6 and 2.7 too):

>>> print '%.16f' % 1.6
1.6000000000000001

>>> print '%.15f' % 1.6
1.600000000000000
paullb
  • 3,995
  • 4
  • 34
  • 61
David Alber
  • 15,924
  • 6
  • 59
  • 67
  • 1
    +1. This answer works in >= Python 2.7. In Python 2.6 it would be `'{0:.16f}'.format(x)`, not sure about older Python. – mtrw Dec 19 '11 at 22:25
  • @mtrw Good point. The "modulo-formatting" (e.g., `'%.16f' % 1.6`) works at least back to Python 2.0 ([Python 2.0 String Formatting Operations](http://docs.python.org/release/2.0/lib/typesseq-strings.html)). – David Alber Dec 19 '11 at 22:37
  • i get a weird error when i try the above code: `# Error: ValueError: zero length field name in format #` – jonathan topf Dec 19 '11 at 22:44
  • @jonathantopf Which version of Python do you have? As @mtrw pointed out in a comment above, if you have Python 2.6, you need the positional argument (the `0` in the code of that comment). This is also true if you have Python 3.0. – David Alber Dec 19 '11 at 23:12
  • @mtrw I updated the answer to use the positional argument and include the "modulo-formatting" for pre-2.6 interpreters. – David Alber Dec 19 '11 at 23:30
  • While this answer is technically true and informative, I do feel it is missing the point of the question. If you `print '{0:.15f}'.format(600.2)` you will notice already non-zero numbers creeping in from the right, and the larger your number, the more "noise" you will see in the decimals. See my answer about using the `decimal` module if you truly care about maintaining 15 digit precision. – dkamins Dec 20 '11 at 18:23
  • I get Syntax errors in Python 3.7 due to lack of brackets. I've added them in – paullb Dec 15 '18 at 00:33
5

The cleanest way in modern Python >=3.6, is to use an f-string with string formatting:

>>> var = 1.6
>>> f"{var:.15f}"
'1.600000000000000'
ruohola
  • 16,015
  • 6
  • 33
  • 67
5

Floating point numbers lack precision to accurately represent "1.6" out to that many decimal places. The rounding errors are real. Your number is not actually 1.6.

Check out: http://docs.python.org/library/decimal.html

dkamins
  • 20,091
  • 6
  • 48
  • 57
3

I guess this is essentially putting it in a string, but this avoids the rounding error:

import decimal

def display(x):
    digits = 15
    temp = str(decimal.Decimal(str(x) + '0' * digits))
    return temp[:temp.find('.') + digits + 1]
BenH
  • 2,012
  • 2
  • 20
  • 33