results of division

Tim Peters tim.peters at gmail.com
Thu Dec 9 11:41:04 EST 2004


[Paul McGuire]
...
> >>> print "%.2f" % 1.775
> 1.77
>
> Hmmm, if we rounded, I would have expected 1.775 to round up
> to 1.78.

Platform-dependent.  1.775 isn't exactly representable regardless, but
whether exactly-half-way numbers that are exactly representable round
up or truncate varies across platform C libraries.  For example, 1.25
is exactly representable in binary fp, but '%.1f' % 1.25 produces 1.3
on Windows but 1.2 on most other platforms (most non-Microsoft C
runtimes use the IEEE "round to nearest or even" rule).

> Perhaps this is a floating point rep issue, that we are really
> rounding 1.7749999999999999999 or something.  Sure enough,
> repr shows us:
> 
> >>> repr(1.775)
> '1.7749999999999999'
> 
> So I added a wee bit to 1.775:
> 
> >>> print "%.2f" % 1.775000000001
> 1.78
> 
> Ok, that looks better.  What if I round explicitly?
> 
> >>> print "%.2f" % round(1.775,2)
> 1.78
> 
> Errr?  How come round() is able to understand 1.775 correctly,
> whereas string interp is not?  I'm guessing that round() adds
> some small epsilon to the value to be rounded,

No way -- that would be insane.

> or perhaps even does the brute force rounding I learned in
> FORTRAN back in the 70's:  add 0.5 and truncate.

Yes, that's what Python's round() does.

>  But this would still truncate 1.779999999 to two places, so this
> theory fails also.

No:

>>> 1.775
1.7749999999999999
>>> 1.775 * 100.0
177.5
>>> 1.775*100 + 0.5
178.0
>>>

That is, before adding 0.5, it multiplies by 100.0.  The vagaries of
binary fp are such that machine_value_for(1.755) * 100 is exactly
175.5, and adding 0.5 to that gives 178 exactly.

> What magic is round() doing, and should this same be done in the
> string interp code?

Python implements round() itself.  Float string formatting is done by
the platform C sprintf().  If you care about decimal representations
so much that you can't tolerate vagaries due to differences in the
53rd significant bit, use the new decimal module instead.



More information about the Python-list mailing list