3

I am using python3.9 and trying to calculate the following:

17.36-14.76. It is a pretty easy calculation and the output should be 2.6 without any other additional digits.

However, in python3.9 I get the following output:

>>> 17.36-14.76
2.5999999999999996

I know, I can round the result to get the desired output. However, I don't understand why it calculates it in a weird manner because 17.36-14.76 IS NOT 2.5999999999999996, 17.36-14.76 is 2.6.

Are there some weird settings python?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Alina
  • 2,191
  • 3
  • 33
  • 68
  • This is because of the Floating-Point Arithmetic pitfall. This is not just Python, as you can't fit an infinite number of bits into memory, so the actual value has to be approximated. – gmdev Jan 31 '21 at 13:01
  • Also see [Is floating point arbitrary precision available?](https://stackoverflow.com/questions/11522933/is-floating-point-arbitrary-precision-available) – Tomerikoo Jan 31 '21 at 13:03
  • Why then is this floating point arithmetic pitfall doesn't apply to "32.90 - 27.97"? What I want to have is just a correct answer that I will find when doing this calculation in google calculator: https://www.google.com/search?client=safari&rls=en&ei=AKoWYLqcC5OSjLsPyIOtgAY&q=17.36-14.76&oq=17.36-14.76&gs_lcp=CgZwc3ktYWIQA1DfzgpY384KYJLRCmgAcAB4AIABW4gBW5IBATGYAQCgAQKgAQGqAQdnd3Mtd2l6wAEB&sclient=psy-ab&ved=0ahUKEwi6nIWcncbuAhUTCWMBHchBC2AQ4dUDCAw&uact=5 – Alina Jan 31 '21 at 13:04
  • 1
    I reopened this because it isn't correct to mark it as a duplicate of a language-agnostic question (which wouldn't mention `Decimal`). – interjay Jan 31 '21 at 13:29
  • It does apply. It all depends on how accurate the approximation is for any given expression. – chepner Jan 31 '21 at 13:49

2 Answers2

5

This is because floating point arithmetic on computers uses base-2 to store numbers rather than our familiar base-10. This means that you don't really have 17.36 and 14.76 there (since you cannot represent them exactly in base-2) but actually an approximation:

>>> f'{17.36:.30}'
'17.3599999999999994315658113919'
>>> f'{14.76:.30}'
'14.759999999999999786837179272'
>>>
>>> f'{17.36-14.76:.30}'
'2.59999999999999964472863211995'

Note that a few numbers such as 1/2 and 1/4 are actually exactly representible using base-2:

>>> f'{.25:.30}'
'0.25'

This is why in general you want to use integers instead of floats if you are caring about exact numbers (such as cent values in currencies).

Another possible workaround is to use the Decimal class (which is essentially just integers that memorized the position of their decimal point). It is important to pass strings here rather than floats:

>>> Decimal('17.36') - Decimal('14.76')
Decimal('2.60')
xjcl
  • 12,848
  • 6
  • 67
  • 89
-3

Use Decimal

>>> from decimal import Decimal
>>> result = Decimal(17.36) - Decimal(14.76)
>>> f'{result:.2f}'
'2.60'
Rodrigo
  • 135
  • 4
  • 45
  • 107
  • 2
    This does not fix it! If you type `Decimal(17.36)` into a terminal you just get `Decimal('17.3599999999999994315658113919198513031005859375')` – xjcl Jan 31 '21 at 13:14
  • Your `f'{result:.2f}'` rounded the result to 2 decimal places, which would have worked with floating point as well. Your use of decimal is wrong as noted in the comment above. – interjay Jan 31 '21 at 13:26
  • https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html – Rodrigo Jan 31 '21 at 13:32