-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why OrderedFloat is not IEEE conformant? #36
Comments
So according to what I could find about the definition of total order provided by IEEE 754, part of it would require that negative zero and positive zero compare differently from the default implementation. In other words, This looks like a big problem because Rust's documentation for
If IEEE-conformant total order is implemented using The only way I can think of to avoid this would be to have a separate trait specifically for floating-point total order. (Btw, this is all based on what I could find from the section I linked above. If I misunderstood something or got something wrong, feel free to correct me.) |
If we would implement This is definition of total order from the standard:
|
@kryptan because people (myself included) still expect these wrappers to behave like a number. The aim is to be as close as possible to how ordering works for the native float types, whilst still upholding the guarantees of Ord. If negative zero compared differently to positive zero it would be useless for me and many other people. It may make sense to have another type that implements the IEEE-defined ordering, but I suspect it will see less usage... |
Hi there! I wanted to revive this topic. As I understand it, the main argument here is that But I see a more important disagreement here between // they are equal, but why?
assert_eq!(OrderedFloat(f64::NAN), OrderedFloat(f64::NAN));
// but division returns NaN (and that's correct!), but if they were truly equal it should result in 1.0
assert_eq!(
OrderedFloat(f64::NAN) / OrderedFloat(f64::NAN),
OrderedFloat(f64::NAN)
); I don't think it's really a good idea to deviate from the standard here 🤔 Moreover, in hash sets they will be represented as single identical element, and that’s wrong. Such expectations may lead to many hidden issues |
Right now, it looks like the question is "Is it possible to comply with one standard (IEEE) without breaking compliance with another standard (the invariants the Rust standard library and ecosystem were promised) and, if not, which standard has worse consequences for breakage?" |
But current implementation breaks mathematical rules and contradicts rust standard library ( |
Then it's a question of whether the two invariants in different parts of the standard library can be reconciled and, if not, which invariant is worse to break. |
In general, I think it can be interpreted in different ways:
rust-lang/rust#57157 (see follow-up PR there)
However it looks like these mentions have been removed from documentation of UPD:
|
There is no such invariant in floating point arithmetic or in Rust’s Also, 0 == 0, but 0 / 0 is not 1. |
Hm, right, that's correct 🤔 But these ones follows the standard at least (and division results generally based on math, there is an explanation for that). While In fact, NaNs are introduced by IEEE 754 (at least their wide usage). |
The standard IEEE 754 Since various requirements (standard comparisons, standard ordering,
|
First of all thanks for detailed answers!
Could you point me to this part, please?
Actually, I'm referring to the comparison behavior. Because as I mentioned earlier, And this is not something expected to me. At least, Comparison with NaN claims:
And:
Thus, I believe IEEE fulfill my expectations. But these are good points actually:
And due to the contradictions, this is probably the only way:
|
IEEE 754-2019 §5.10 states:
|
In fact,
So, I think there is no any issue here. As it's expected and explicitly stated. It was just not entirely clear why this was so. But these contradictions explain the chosen behavior. Thank you for quick and detailed replies! |
Btw, I'm not sure there would be a contradiction if Based on Rust's documentation (see comment above), there is no mention about transitivity. It's seems logical to apply, but might not be necessary.
It doesn't mean that WDYT? 🤔 |
That's exactly what "if and only if" means. |
Oh, right, it's biconditional statement Thanks, for some reason I totally ignored "iff" |
Btw, I think you're talking about symmetry here rather than transitivity. Symmetry is the property that |
Yes, you're absolutely right! In general, I have no more questions. Thanks everybody for answers! |
For
OrderedFloat
:IEEE standard requires different NaNs to be not equal, positive NaN to be greater than +∞ and negative NaN to be less than -∞. It also requires -0 to be less than +0. Why non-conformant behavior was chosen? Wouldn't it make more sense to implement total order as defined in standard instead?
This Stack Overflow answer is presumably providing a fast way to implement IEEE total order comparison.
The text was updated successfully, but these errors were encountered: