I understand what you are talking about, but I tend toward just making
it one of the things to remember when working with floats.  (I've been
bitten a lot when I forget to use '==' instead of '=', too!)

Yeah, but it threw me for a loop, because I could find *no*e way to compare a
float and an integer and get it to come out right before I remembered round.


As you say, the problems arise when you try to make comparisons. To get
around the difficulties with comparisons, I wrote a helper function:

###
Python 2.3 (#2, Jul 30 2003, 11:45:28)
[GCC 3.1 20020420 (prerelease)]
Type "copyright", "credits" or "license" for more information.
MacPython IDE 1.0.1
>>> from math import floor, log10
>>> def Round(x, n=0, sigfigs=False):
'''An enhanced rounder which rounds to the nth significant digit
(the nth digit from the first non-zero digit, not the nth decimal place)
    if the parameter sigfigs is not zero.
    This uses "round-up" decisions when the digit following the one of
    interest is a 5, i.e. 1.35 and 1.45 Round to 1.4 and 1.5 when sigfigs
= 2.
'''
if x==0: return 0
if not sigfigs:
return round(x,n)
else:
return round(x,n-1-int(floor(log10(abs(x)))))
###

And here's a helper that uses it to check for equality of two numbers
(floats, or otherwise)
to whatever number of digits you desire --starting from the first non-zero
digit, The default is for high precision.

###
>>> def same(x,y,prec=9):
"""Return True if x and y are the same after being rounded to the same
degree of precision."""
return Round(x,prec,1)==Round(y,prec,1)
..
>>> print same(1.3,1.31,3) #at the 3rd digit these are different
False
>>> print same(1.3,1.31,2) #at the second digit they are (rounded to)
the same digit number
True
>>> same(64.0**(1/3.0) ,4) #here's your example
True
###

You can be bitten by any comparison, not only tests for equality, too.

###
>>> while 1:
..  i+=.1
..  if i>2.1:break
..
>>> print i
2.1
###

It doesn't look like the last value of i was really greater than 2.1--it's
actually 2.1000000000000005 so the result is correct (though not what we
expected). We don't have the problem with a step size of 0.7 in this case,
though, because the value before 2.8 was 2.0999999999999996--just a little
smaller than 2.1.

Here, we specify the precision and get the desired result.

###
>>> i=0
>>> while 1:
..  i+=.1
..  if round(i,9)>round(2.1,9):break
..
>>> print i
2.2
###


Wish granted in version 2.4 ;-) I don't have it on the mac, but there is a write-up at

I meant in the scripts -- even better, as a builtin.

Your above helper function is fine... but I believe that it should be part
of the __cmp__ method of the float types. Perhaps with optional parameter?
Such as oldway=True

Jacob Schmidt

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to