Tuesday, June 26, 2018

Unexpected behavior of Python in integer division

There turns out to be a number of cases where Python give you results different from your expectation, or from your implicit assumption from years of math experience. Described here are the two representative cases that gave me quite a bit of headache to figure out while trying Project Euler problems #91 and #160. In both lessons, my codes had to work since they had nothing complicated, but they didn't. Then I need to suspect every single bit of logical steps involved, double checking whether they work exactly as I expect them to.

The first case was about the division operation between integers, particularly when you have a number which is an integer multiple of another: 15 * 26 / 13 gives you 30.0 but 15 / 13 * 26 gives 29.999999999999996. The latter is probably satisfactorily close to, BUT LOWER THAN the expected value of 30. It may not be an issue if this is your final output, but it can make a big difference if you use it as intermediate result subsequently fed to a case statement executing completely different codes depending on whether it is greater or less than 30. The reason is obvious: because division operation is always executed as floating point numbers, even when both arguments are integers.

Implicit conversion to floating point numbers can cause a different type of trouble in integer division: lost significant digit / precision. Python is famous for allowing unlimited number of significant digits to represent integer, but not floating point number. You might expect that Division of A = 265252859812191058636308480000000 by B = 10 removes a zero at the end, retaining all other significant digits. But you will lost many digits by going through floating point number.

How can we avoid this pitfall? Make sure to use true inter-integer operators such as // or %. Unlike A/B, A//B gives the correct and expected answer.

C seems to be free from this issue. Both 15 * 26 / 13 and 15 / 13 * 26 gives 0.000000.

-------------------------------------------------------

Two opposite sides of programming: it can easily drive you nuts, but at the same time you can crack it all the way down to binary digit (0 vs. 1) level as long as you are willing to and are persistent.

No comments:

Post a Comment

Philips SAECO Xsmall espresso machine repaired

I have a SAECO Xsmall espresso machine. I bought it in Dec 2014, and brewed 2~3 cups of espresso per day on the average over the last 6 year...