0

Df.round() is returning frustrating results.

In the following example, I am trying to round a decimal to five digits. Each decimal has a 5 in the sixth decimal position. When I round, I expect the fifth decimal value to round up. This only happens sometimes..

df2 = pd.DataFrame([0.703125, 0.831215])
df2
Out[4]: 
          0
0  0.703125
1  0.831215
df2.round(5)
Out[5]: 
         0
0  0.70312
1  0.83122

After some googling, it sounds like the issue relates to how floating point numbers are represented by the computer. What's a practical way to get around this issue?

rvictordelta
  • 630
  • 2
  • 8
  • 23
  • 5
    Pandas used `numpy.around` to round the numbers. See https://docs.scipy.org/doc/numpy/reference/generated/numpy.around.html#Notes "For values exactly halfway between rounded decimal values, NumPy rounds to the nearest even value" – KPLauritzen Jun 04 '18 at 13:14

1 Answers1

4

You say "I expect the fifth decimal value to round up". OK, but in what circumstances? Given that your example inputs only have 6 significant digits, and a Python float (64-bit) supports about 15 digits, you can safely add a tiny amount to get the behavior you want:

(df2 + 1e-12).round(5)

It gives:

         0
0  0.70313
1  0.83122

This assumes the largest value in df2 is under 1000 or so, and the smallest value is less than about 1e-6 assuming 6 sigfigs. The addition of a small amount makes sure any trailing "5"s are rounded up, so long as your inputs are within some known range where the small addition won't make the results incorrect.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • This... worked. Will this always work? Inaccuracy caused by floating point representation issue is never greater than 1e-12? – rvictordelta Jun 04 '18 at 13:26
  • The inaccuracy comes into play after about 15 significant digits. So if your input is large, say 1e20, this solution will have no effect at all. But if your inputs are in the range `[1e-6, 1e3]`, this solution should be OK. – John Zwinck Jun 04 '18 at 13:32
  • Wonderful. Thank you – rvictordelta Jun 04 '18 at 15:09