-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
EPSILON is a bad error margin and should not be recommended [float_cmp] #6816
Comments
When I was still writing float-heavy code, I always had a function to calculate a suitable epsilon-value based on the values to compare and the number of mantissa bits that I expected to be equal. |
So then should we lint against |
This also has implications for |
I'm not completely certain. In cases where That said, I do think that To be extra pedantic, a pedantic lint against I don't have any strong opinions on linting float comparisons, though, beyond not recommending comparison against machine epsilon. |
The old classic "What Every Computer Scientist Should Know About Floating-Point Arithmetic" says that when a real number is rounded to the closest floating point number it's relative error is bounded by machine epsilon. Note that is relative error not absolute. So based on that I would expect the correct comparison to be |
Oh, it looks like |
This bad suggestion came up on URLO. |
This came up on IRLO again and will likely continue to do so until this is somehow categorically fixed. |
Is it that hard? The test should be:
where But before we do any of the above, consider alternatives:
|
Also, I'd say use |
A backward-stable algorithm evaluating a function |
Submitted #13079 to fix this. As already described above in this thread, there are further implications for |
…=y21 Fix guidance of [`float_cmp`] and [`float_cmp_const`] to not incorrectly recommend `f__::EPSILON` as the error margin. Using `f32::EPSILON` or `f64::EPSILON` as the floating-point equality comparison error margin is incorrect, yet `float_cmp` has until now recommended this be done. This change fixes the given guidance (both in docs and compiler hints) to not reference these unsuitable constants. Instead, the guidance now clarifies that the scenarios in which an absolute error margin is usable, provides a sample implementation for using a user-defined absolute error margin (as an absolute error margin can only be used-defined and may be different for different comparisons) and references the floating point guide for a reference implementation of relative error based equality comparison for cases where absolute error margins cannot be identified. changelog: [`float_cmp`] Fix guidance to not incorrectly recommend `f__::EPSILON` as the error margin. changelog: [`float_cmp_const`] Fix guidance to not incorrectly recommend `f__::EPSILON` as the error margin. Fixes #6816
`float_cmp` changes fixes #2834 fixes #6816 --- changelog: This: * Deprecated `float_cmp_const` in favor of a config option on [`float_cmp`]. [#11948](#11948) * [`float_cmp`]: Don't lint literal and self comparisons. [#11948](#11948) * [`float_cmp`] [#11948](#11948) * Add the [`float-cmp-ignore-named-constants`] configuration to ignore comparisons to named constants. * Add the [`float-cmp-ignore-change-detection`] configuration to ignore const-evaluatabled values. * Add the [`float-cmp-ignore-constant-comparisons`] configuration to ignore comparisons to the modification of an operand (e.g. `x == f(x)`).
[f32|f64]::EPSILON
are the machine epsilon of the type, or (as stated in the Rust docs), the distance between1.0
and the next representable floating point number.The page linked in the more info specifically says that
abs( a - b ) < epsilon
is wrong for any value ofespilon
. However, it's especially egregious withf__::EPSILON
, because for floating point numbers outside the range-2..=2
, floating point numbers cannot bef__::EPSILON
close, soabs( a - b ) < f__::EPSILON
is actually equivalent to a strict equality check.There isn't a generally applicable solution to recommend. The most thorough resource I've found suggests comparison in ULPs for testing against a non-zero number, and testing against a fixed epsilon (but one bigger than
f__::EPSILON
.At the least, we (and probably std) shouldn't be recommending comparing against
f__::EPSILON
, as it's basically as poor as bitwise equality and gives a false sense of handling the problem, when it isn't really handled.The text was updated successfully, but these errors were encountered: