math.nroot [was Re: A brief question.]

Steven D'Aprano steve at REMOVEMEcyber.com.au
Sun Jul 3 23:29:36 EDT 2005


George Sakkis wrote:
> "Tom Anderson" <twic at urchin.earth.li> wrote:
> 
> 
>>>But NaNs are _not_ things.
>>
>>I disagree. A NaN _is_ a thing; it's not a floating-point number, for
>>sure, but it is a symbol which means "there is no answer", or "i don't
>>know", and as such, it should follow the universal rules which apply to
>>all things.
> 
> 
> It seems that the standard semantics of NaN is closer to NULL values in
> ANSI SQL, that is "unknown", "not available". In this sense, if you
> have two 'things' you don't know, you can't say they are equal simply
> because you don't know them !

It isn't that they are unknown. They don't exist, so 
you can't compare them! The bit-patterns that represent 
NaNs should not be thought of as "the answer to the 
calculation", but merely "a flag representing the fact 
that an error occurred".

The nice thing is that the flag can propogate through 
your calculations, so you can defer testing for an 
error condition until the very end, but it is not a value.

When you think of NaNs as flags, the question of 
equality doesn't apply. You can compare two flags bit 
by bit to see if they have the same bit pattern, and 
that's what the isNan() function is for: test if a 
float has a bit pattern that represents a NaN.

But it doesn't make sense to say that two flags are equal:

keep_processing = True
more_reading_needed = True
while more_reading_needed and keep_processing:
     get_more_records()
     process_records()
if not keep_processing:
     print "User clicked Cancel"

What does it mean to say that the flag done_processing 
is equal to the flag more_reading_needed? (That is not 
the same question as asking if the two flags have the 
same value.)



>>>Since INF-INF doesn't have an answer, we can't do this:
>>>
>>>x = inf - inf
>>>y = inf - inf
>>>
>>>and expect that x == y.
>>
>>I think we can. Both x and y have the same value, a value of
>>indeterminacy. NaN is a rigidly defined value of doubt and uncertainty!
> 
> 
> In this case, however, I would agree. x and y above are not assigned a
> label of 'unknown'; they are derived from an operation among valid
> *known* values, so NaN here means 'invalid' rather than 'unknown'.It
> makes sense to have x==y, because x and y are the outcome of the *same*
> invalid operation.

This is incorrect. Mathematically, you CAN'T say:

x = INF - INF
y = INF - INF

therefore x = y. This is just _wrong_. Mathematically, 
x and y don't exist, so they can't be equal since 
equality is only defined for things which exist.

It gets worse. Consider this example of "logic":

x = log(-5)  # a NaN
y = log(-2)  # the same NaN
x == y  # you want this to be true for NaNs

Then:

# compare x and y directly
log(-5) == log(-2)
# if x == y then exp(x) == exp(y) for all x, y
exp(log(-5)) == exp(log(-2))
-5 == -2


> Similarly, if z=0/0, z would also be invalid, but
> different from x and y, since it is the result of a different invalid
> operation. This brings us to the many-NaN situation.

The problem is, the many NaNs in the IEEE standard (or 
at least Apple's implementation of it) refer to _kinds_ 
of NaNs, not NaNs themselves.

log(-2) is not the same "not a number" as log(-2.0001), 
or log(-2.3). They might be the same "kind" of failure, 
but that's it.

You can't even say that log(-2) == log(-2), because 
equality is only defined for numbers, not "no such thing".

Having given reasons why it is utterly bogus to be 
comparing NaNs for equality, I will say this. 
Practicality beats purity. If you can demonstrate a 
good usage case for testing equality with NaNs, I will 
accept that it is a good thing to do.

if x in (SOME_NAN, SOME_OTHER_NAN, ANOTHER_NAN, \
     YET_ANOTHER_NAN, AND_ANOTHER_NAN, ..., \
     # 240+ more NaNs listed
     ALMOST_FINISHED_NOW, LAST_NAN):
     print "Calculation failed!"

is _not_ a good usage case, since it is best handled with:

if isNan(x):  # handled by the floating point package
     print "Calculation failed!"


-- 
Steven.




More information about the Python-list mailing list