3

I don't understand why % works like this:

>>> 5 % 0.5 == 0
True
>>> 5 % 0.25 == 0
True
>>> 5 % 0.2 == 0
False
>>> 5 % 0.1 == 0
False

Can someone explain this to me? I need to check if user input divides a series of numbers. Program accepts the input only if all numbers are divisible by user input, otherwise it asks the user for another number.

Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
Pigna
  • 2,792
  • 5
  • 29
  • 51

2 Answers2

5

Note that:

  • 0.5 is 2**-1
  • 0.25 is 2**-2
  • 0.625 is 2**-1 + 2**-3 and so on.

So, as long you have a perfectly representatble floating point number, there is a good possibility that the division/modulo operation will go through smoothly.

However, when you try to divide (or take modulo) by 0.1 or 0.2, there is always a roundoff error in its floating point representation, which means the division will not be complete, and hence the result will not be True.

You can use the Decimal module for more correct operations. Also, go through the regular pitfalls of floating point number.


>>> 1000 % 0.25 == 0
True
>>> 1000 % 0.625 == 0
True
Anshul Goyal
  • 73,278
  • 37
  • 149
  • 186
  • 1
    Sometimes the result is `True` although there is error in the floating-point representation. For instance `0.4 % 0.1 == 0`, without looking, although neither of these binary floating-point number is exactly what the decimal representation implies, because the first is still exactly 4x the second. – Pascal Cuoq Aug 13 '15 at 12:58
  • In the end I simply rounded up the operation: round(5 % 0.1) == 0 Is it a good practice? – Pigna Aug 14 '15 at 11:09
  • @Pigna No, that is not a good practise, for the simple reason that `round(5%1.1) == 1` will also be True, though it shouldn't really be the case since that is not what your question intended. Use the decimal module, it is made for such situations only – Anshul Goyal Aug 14 '15 at 15:00
1

Rounding errors in the floating point arithmetic.

>>>5 % 0.5
0.0
>>>5 % 0.25
0.0
>>>5 % 0.2
0.19999999999999973
>>>5 % 0.1
0.09999999999999973
Jamie Bull
  • 12,889
  • 15
  • 77
  • 116