Re: Comparing floats
On 29 nov, 00:20, Nobody wrote: > On Sat, 27 Nov 2010 18:23:48 -0500, Terry Reedy wrote: > >> Therefore, to implement this multiplication operation I need to have a > >> way to verify that the float tuples C and D are "equal". > > > I might try the average relative difference: > > sum(abs((i-j)/(i+j)) for i,j in zip(C,D))/n # assuming lengths constant > > The division is unstable if i and j are close to zero. > > For scalars, I'd use: > > abs(i-j) <= epsilon * (1 + abs(i+j)) > > This amounts to a relative error check for large values and an absolute > error check for values close to zero. > > For a vector, I'd check that the above holds for all pairs. Hi All, Why don't you treat the C and D tuples as vectors? You can than check dot product and norm (length) for equality. Using scipy (www.scipy.org), you even get very nice performance. Marco -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparing floats
On Sat, 27 Nov 2010 18:23:48 -0500, Terry Reedy wrote: >> Therefore, to implement this multiplication operation I need to have a >> way to verify that the float tuples C and D are "equal". > > I might try the average relative difference: > sum(abs((i-j)/(i+j)) for i,j in zip(C,D))/n # assuming lengths constant The division is unstable if i and j are close to zero. For scalars, I'd use: abs(i-j) <= epsilon * (1 + abs(i+j)) This amounts to a relative error check for large values and an absolute error check for values close to zero. For a vector, I'd check that the above holds for all pairs. -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparing floats
kj wrote: > I understand that, in Python 2.7 and 3.x >= 3.1, when the interactive > shell displays a float it shows "the shortest decimal fraction that > rounds correctly back to the true binary value". Is there a way > to access this rounding functionality from code that must be able > to run under version 2.6? (The idea would be to implement float > comparison as a comparison of the rounded versions of floats.) Doesn't float(str(x)) == x for all x imply that str(x) == str(y) if and only if x == y? If so, what would be the benefit of converting to string at all? -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparing floats
On Sat, 27 Nov 2010 22:55:10 +, kj wrote: [...] > Therefore, to implement this multiplication operation I need to have a > way to verify that the float tuples C and D are "equal". That C and D are tuples of floats is irrelevant. The problem boils down to testing floats for equality. It's easy to test two floats for equality, that's exactly what == does, but two floats which should be equal might not be due to calculation errors. To work around this, we loosen the definition of "equal" to give some allowance for rounding errors. Unfortunately, you need to decide what you mean by "two floats are equal", since that will depend on the semantics of your problem and data. There is no standard answer that applies everywhere. I suggest you leave it up to the user to decide what tolerance their data can support, and offer a sensible default for cases that they don't know or don't care. This might be useful for you, or at least give you some ideas: http://code.activestate.com/recipes/577124-approximately-equal/ [...] > The only approach I know of is to pick some arbitrary tolerance epsilon > (e.g. 1e-6) and declare floats x and y equal iff the absolute value of x > - y is less than epsilon. The four basic approaches are: (1) Is the absolute difference between the values <= some tolerance? (2) Is the relative difference between the values <= some tolerance? (3) Round the two values to a fixed number of decimal places, then compare for equality. This is a variation on (1) above. (4) How many differences in the least significant bits of the two values do we accept? > I understand that, in Python 2.7 and 3.x >= 3.1, when the interactive > shell displays a float it shows "the shortest decimal fraction that > rounds correctly back to the true binary value". Is there a way to > access this rounding functionality from code that must be able to run > under version 2.6? (The idea would be to implement float comparison as a > comparison of the rounded versions of floats.) How do you expect to access code in the Python 2.7 interpreter from Python 2.6? If you have 2.7 available, just use 2.7 :) It is a standard, royalty-free algorithm that you can find on the Internet somewhere. Worst case, you could copy it from the Python 2.7 source code, re-write it in Python if need be, and distribute it in your own application. But I don't think it will help you, since it isn't dealing with the fundamental problem that: * equality between two floats is well-defined, but not useful * equality given some tolerance is useful, but not well-defined (there is no tolerance that is always best, and there is no general way to decide whether absolute or relative error is more important) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparing floats
Terry Reedy writes: > On 11/27/2010 5:55 PM, kj wrote: > >> Therefore, to implement this multiplication operation I need to >> have a way to verify that the float tuples C and D are "equal". > > I might try the average relative difference: > sum(abs((i-j)/(i+j)) for i,j in zip(C,D))/n # assuming lengths constant That'll throw an exception if i == -j. You could replace (i+j) with math.hypot(i, j) or abs(i)+abs(j) but it will still fail when i == j == 0. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list
Re: Comparing floats
On 11/27/2010 5:55 PM, kj wrote: Therefore, to implement this multiplication operation I need to have a way to verify that the float tuples C and D are "equal". I might try the average relative difference: sum(abs((i-j)/(i+j)) for i,j in zip(C,D))/n # assuming lengths constant Certainly, I want to do this in in a way that takes into account the fact machine computations with floats can produce small differences between numbers that are notionally the same. The problem is that the appropriate value may depend on the application and the source of the floats. If they are measured to 3 decimal places, you need a large value. If they are calculated, you need much smaller. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Comparing floats
I'm defining a class (Spam) of objects that are characterized by three parameters, A, B, C, where A and C are n-tuples of floats and B is an n*n tuple-of-tuples of floats. I'm defining a limited multiplication for these objects, like this: Spam(A, B, C) * Spam(D, E, F) = Spam(A, dot(B, E), F) if and only if C == D. (Here dot(B, E) represents the matrix multiplication of B and E). In other words, this multiplication is defined only for the case where the last parameter of the first object is equal to first parameter of the second object. An exception should be thrown if one attempts to multiply two objects that fail to meet this requirement. Therefore, to implement this multiplication operation I need to have a way to verify that the float tuples C and D are "equal". Certainly, I want to do this in in a way that takes into account the fact machine computations with floats can produce small differences between numbers that are notionally the same. E.g. (in Python 2.6.1 at least): >>> 49.0 * (1.0/49.0) 0.99989 >>> 1.0 == 49.0 * (1.0/49.0) False The only approach I know of is to pick some arbitrary tolerance epsilon (e.g. 1e-6) and declare floats x and y equal iff the absolute value of x - y is less than epsilon. Does the Python standard library provide any better methods for performing such comparisons? I understand that, in Python 2.7 and 3.x >= 3.1, when the interactive shell displays a float it shows "the shortest decimal fraction that rounds correctly back to the true binary value". Is there a way to access this rounding functionality from code that must be able to run under version 2.6? (The idea would be to implement float comparison as a comparison of the rounded versions of floats.) Absent these possibilities, does Python provide any standard value of epsilon for this purpose? TIA! ~kj -- http://mail.python.org/mailman/listinfo/python-list