round issue

R

Robin Becker

A client wants to know why his db number -9.85 gets displayed by some simple
code as -9.8

I looked at the number and see that
-9.8499999999999996

ie I expect simple rounding to produce the observed result and indeed
'-9.8'

however, when I use round I get an unexpected result ie-9.9000000000000004

according to its definition
round(x[, n])¶
Return the floating point value x rounded to n digits after the decimal point.
If n is omitted, it defaults to zero. The result is a floating point number.
Values are rounded to the closest multiple of 10 to the power minus n;
if two multiples are equally close, rounding is done away from 0 (so. for example,
round(0.5) is 1.0 and round(-0.5) is -1.0).

so looking at the absolute differences I see
0.049999999999998934

ie the -9.8 value appears closer and at least to a primitive test
True

the distance from the -9.9 result is larger, however, that may be because the
model numbers for -9.8 & -9.9 differ in distance from the true 10**-n values eg
-9.8000000000000007

What value should round(-9.85,1) return? Is the result explainable in python (ie
without resort to the internal FP representations etc etc)?
 
M

Mark Dickinson

What value should round(-9.85,1) return? Is the result explainable in python (ie
without resort to the internal FP representations etc etc)?

As you observe, the closest float to -9.85 is actually just a little
smaller (i.e., closer to 0) than -9.85:

Python 2.7 (r27:82500, Jul 11 2010, 22:38:53)
[GCC 4.2.1 (Apple Inc. build 5659)] on darwin
Type "help", "copyright", "credits" or "license" for more information.Decimal('-9.8499999999999996447286321199499070644378662109375')

So you're right: round(-9.85, 1) *should* return -9.8. The 2.x (for x
<= 6) version of round is a bit deficient in that respect.
Internally, it's doing the obvious thing: namely, multiplying by
10.0, rounding to the nearest integer, then dividing by 10.0. The
problem is that this not-quite-9.85 value, when multiplied by 10,
becomes (as a result of rounding error) *exactly* 98.5, which then
gets rounded *up* to 99 instead of down to 98.

This is fixed in Python 2.7, and in Python 3.x. (The code that was
introduced for the new short float repr made it easy to fix.)

That said, if your client really *means* -9.85 (rather than some
binary approximation to it), and wants it to round in a predictable
manner, the right way to fix this would be to use Decimal instead of
float to represent the number. That way, you can also specify what
rounding mode you want (instead of relying on the default round-half-
away-from-zero in 2.x or round-half-to-even in 3.x.)
Decimal('-9.8')
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top