round issue

Mark Dickinson dickinsm at gmail.com
Mon Jul 12 14:59:35 EDT 2010


Emile van Sebille <emile <at> fenx.com> writes:

> 
> On 7/12/2010 2:52 AM Robin Becker said...
> <snip>
> > What value should round(-9.85,1) return?
> 
> Per round's definition, -9.9.

No.  The float that's represented by the literal '-9.85' *isn't*
exactly -9.85, for all the usual binary floating-point reasons.
The value that gets stored is a tiny amount smaller (i.e., closer
to zero) than -9.85, so according to the definition it should
round *down*, to -9.8.  (Or rather, to a float that's very close
to, but not exactly equal to, -9.8.)

>  String interpolation for %n.mf doesn't 
> appear to define it's rounding behavior, so a peek at the source would 
> answer what's being done.

In Python 2.6, the string interpolation delegates to the system,
so it does whatever C string formatting does.  Usually that's
rounding to nearest, with exact halfway cases rounded to
even.  In Python 2.7 and 3.x, Python has its own code for
string formatting, and again it rounds to nearest, rounding
ties to even.

> It does look inconsistent however, and it seems to me rounding and 
> interpolation should behave similarly.

Agreed.  In this case it's a minor bug that round(-9.85, 1)
produces -9.9 instead of -9.8;  both string formatting
and round should give -9.8.  This bug is fixed in Python
2.7 and in Python 3.x.

Note that in 2.7 there's still a legitimate difference: round
rounds halfway cases away from 0, while string formatting
rounds them to even.  So the following results are correct:

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.
>>> round(1.25, 1)
1.3
>>> '%.1f' % 1.25
'1.2'

(1.25 *is* an exact halfway case, since it's exactly
representable as a binary float.)

In Python 3.x, round always does round-half-to-even, so
string formatting and round should agree (and if they don't,
it's definitely a bug: please report it!)

With all this said, asking for *decimal* rounding of
*binary* approximations to *decimal* halfway cases to give
the results you expect is ... optimistic, to say the least.
Use the decimal module if you care about which way
your (almost) halfway cases get rounded.

[I already replied to this earlier through Google groups, but
I'm not sure whether it went through properly.  Apologies
for the duplication, if so.]

-- 
Mark





More information about the Python-list mailing list