[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. -- http://mail.python.org/mailman/listinfo/python-list