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