> (Dictionary new at: Float nan put: 'nan'; yourself) printString
>
> Also, I'm interested in your commentary on the first example too..
>
> (Set with: Float nan) includes: Float nan "false"
>
> do you think these are bugs?
No, I think these are not bugs. First, this has nothing to do with
Sets and Dictionaries, it is a property of Float. First, try this:
Float nan = Float nan You obtain false. At first sight, this is a
surprise, but it is possible to defend this result with good reasons.
Look at this:
1.0e200 tan = 1.0e200 tan gives false and
1.0e200 tan = 1.0e200 sin gives also false.
This last example is the key to a better understanding of the
properties of NaNs. A NaN represents the result of a computation that
can not be represented as a Float value.
As we can certainly not say that
1.0e200 sin and 1.0e200 tan are equal,
it is best to assume that two NaNs are never equal. (Database
progammers will remember similar rules for NULL values. Two NULL
values are never considered to be equal, simply because the represent
unknown entities).
From the Intel documentation of instruction FCOm (Float COMpare)
>>If either operand is a NaN or is in an unsupported
>>format, an invalid-arithmeticoperand exception (#IA)
>>is raised and, if the exception is masked, the condition
>>flags are set to "unordered." If the invalid-arithmetic-
>>operand exception is unmasked, the condition code
>>flags are not set.
This means that NaNs are never considered to be equal. Note also that
NaN is not represented by a single bit pattern: There are a lot of
different representations of NaN: A NaN is an invalid floating-point
result that has all ones in the exponent with a significand that is
not all zeros.
Hope this helps, Boris
----------
Is this a bug?
It's certainly an interesting question.
Set and Dictionary assume that (x = x) always answers true.
However, the IEEE 754 and IEEE 854 standards (and the IEC revision,
and the draft revision of IEEE 754 that I believe is still in progress)
is quite explicit that if x is a NaN, x does NOT equal itself.
In fact, that's one way to test whether something is a NaN:
Float>>isNaN
^self ~= self
I suggest that the behaviour of Set here is the simplest behaviour which
is consistent with both Set (find an element that is #= to the argument)
and IEEE 754 (NaNs are not equal to themselves).
(Dictionary at: Float nan put: 'NaN') is an attempt to mess with
the Dictionary class itself. Since Dictionary is not an indexable
object (Dictionary class isVariable => false) the primitive fails.
(Dictionary new) at: Float nan put: 'NAN'; printString
pops up an 'Error: key not found' due to Dictionary>>at: Float nan.
One would have expected that printing a Dictionary containing n
bindings would be O(n) + the cost of printing the keys and the values.
It isn't. Thanks to the use of #keysSortedSafely, it's O(n.lg n) + ...
And #keysSortedSafely has its own problems: it is not clear to me that
the sort order it uses would be consistent in the absence of NaNs, but
it's quite clear that it's NOT consistent in the presence of NaNs.
What I'm getting at here is that a good sorting algorith which has
found that x <= y and y <= z will often not bother to check whether
x <= z, because it "knows" that it is. Well,
NaN < 2.0 is false, so 2.0 <= NaN (x <= y)
1.0 < NaN is false, so NaN <= 1.0 (y <= z)
But is it true that 2.0 <= 1.0 (x <= z)?
If it comes to that,
1.0 < NaN is false, NaN < 1.0 is false, but NaN is not equal to 1.0
Does anyone know why #keysSortedSafely is used? Who is 'sma'?
Dictionary printing would be faster and safer without it.
Set printing doesn't run into this problem because it doesn't sort.
Why sort Dictionaries but not Sets?
For what it's worth, in Ambrai Smalltalk
|z n s|
z := 0.0.
n := z/z.
s := Set with: n.
s includes: n
=> false
and
|z n d|
z := 0.0.
n := z/z.
d := Dictionary new.
d at: n put: 'NaN'.
d printString
=> 'Dictionary(NaN->(''NaN''))'
and
d at: n
throws a 'key not found' ErrorMessage.
O'Keefe
-----
I remember researching this to try and get VW up to date w.r.t. ieee fp
math and learning something interesting things about NAN. It is the
singularity event horizon of fp math. Any math you do with it will turn
into a NAN. Even +/-infs. All roads lead to NAN. And when you get
there, it refuses to be "truth"ful about anything. It is not = to
itself or anything else for that matter. It gets better. It's not
greater or less than itself. Or anything else. Greater than or equal
and the flip don't work either. The thing is the "false" hole.
Travis Griggs
---
Is it true, that we could have
aNaN == aNaN & (aNaN ~= aNaN) -> true
(identity but not equality) here?
So try it in a Workspace:
x := Float nan.
(x == x) & (x ~= x)
=> true
So yes, that does actually happen. And there are 2*(2**53-1) bit patterns
that count as IEEE Not-a-Numbers. (Sign field can be + or -, exponent
field must be 0, significand must not be 0 because that would be Infinity.)
RAOK