My preference in tests is a little different than just using IEEE 754 ==, _Bool equiv(float x, float y) { return (x which both handles NaNs sensibly (all NaNs are equivalent) and won't warn about using == on floats. I find it also easy to remember how to write when starting a new project.
It's OK to compare floating-points for equality
131–140 of 150 posts
Re: It's OK to compare floating-points for equality
#132I have this floating-point problem at scale and will donate $100 to the author, or to anyone here, who can improve my code the most. The Rust code in the assert_f64_eq macro is: if (a >= b && a - b I'm the author of the Rust assertables crate. It provides floating-point assert macros much as described in the article. https://github.com/SixArm/assertables-rust-crate/blob/main/s... If there's a way to make it more prec…
match a - b {
d if d >= 0.0 => d d >= -f64::EPSILON, /* true if -EPSILON to -0.0 */
}
https://godbolt.org/z/71PGzd7oaRe: It's OK to compare floating-points for equality
#133Earlier quoted context omitted.
Is there any constant more misused in compsci than ieee epsilon? :) It's defined as the difference between 1.0 and the smallest number larger than 1.0. More usefully, it's the spacing between adjacent representable float numbers in the range 1.0 to 2.0. Because floats get less precise at every integer power of two, it's impossible for two numbers greater than or equal to 2.0 to be epsilon apart. The spacing between 2…
The term I've seen a lot is https://en.wikipedia.org/wiki/Unit_in_the_last_place So I'd probably rewrite that code to first find the ulp of the larger of the abs of a and b and then assert that their difference is less than or equal to that. Edit: Or maybe the smaller of the abs of the two, I haven't totally thought through the consequences. It might not matter, because the ulps will only differ when the numbers are…
Re: It's OK to compare floating-points for equality
#134Earlier quoted context omitted.
Nobody's code will be compiled to use x87 any more.
There is plenty of demand for so called "secure code", where such coder arrogance will not be tolerated. Trust me on that, I know it.
It is also faster and more precise to use double-double for math over x87 extended precision. There is literally no reason to compile an x87 instruction today aside from a programmer not knowing better.
Re: It's OK to compare floating-points for equality
#135Earlier quoted context omitted.
I think his point is: rather than "leaning into" it as in, masking through epsilons, he argues that tolerance is fundamental to the problem space, not a way to resolve edge cases.
Right. And my point is that "leaning in" doesn't mean masking, it means committing to. Taking seriously. Exactly the sort of thing he's describing. I'm wondering if people have heard the expression "leaning in" from people who were insincere/lying, and assumed that that was what the phrase means?
Re: It's OK to compare floating-points for equality
#136My preference in tests is a little different than just using IEEE 754 ==, _Bool equiv(float x, float y) { return (x which both handles NaNs sensibly (all NaNs are equivalent) and won't warn about using == on floats. I find it also easy to remember how to write when starting a new project.
assert(x == 7); // fine
assert(y == NaN); // never true
assert(y != y); // this is what you meant
so this equiv() helper fixes that, assert(equiv(x, 7)); // fine
assert(equiv(y, NaN)); // also fine
now, as far as treating NaNs equivalently, the IEEE 754 float format has a huge number of possible representations of NaN, and if you did something like a bitwise comparison, you might think that 0x7fc00000, 0x7f800001, 0xffc00000, 0x7fc0f00d were all different and not equivalent, but they're all NaNs, and I find that when I'm looking for a NaN, I very rarely care about exactly which one I'm looking at. So checking (x!=x && y!=y) admits any two NaNs as equivalent.Re: It's OK to compare floating-points for equality
#137There are perfectly good solutions for finding the angle using atan and the cross product. Calculating A x B will yield a vector which lies is along their normal with length tan(θ)(A · B) so we can straightforwardly say e.g.:
`θ = atan2(norm(A ⅹ B), (A · B))`
No thresholds, no branching, only ~1 bit of significance lost. As the original author says himself, when you're introducing arbitrary-feeling thresholds, it's likely you're missing a solution which would improve more than just the weirdness at those thresholds.
[0] A good analysis of this is on Page 46 here, including a more optimized (but less obviously true) alternative to the formula above: https://people.eecs.berkeley.edu/~wkahan/Mindless.pdf
Re: It's OK to compare floating-points for equality
#138Earlier quoted context omitted.
> This is a fundamentally unsolvable problem with floating point math It's a fundamentally unsolvable problem with B-reps ! The problem completely disappears with F-reps. (In exchange for some other difficult problems).
>(In exchange for some other difficult problems). Ahhaha. (I used to work in nTop, and boy is this an understatement when it comes to field based solid modeling)
It's very deceptive because the easy way works so well (Use smoothmin instead of min and you get smooth blends for free! You can even use a circular approximation of smoothmin and get proper fillets!). But when you want the user to be able to pick a couple of surfaces and fillet between them, it gets really hard.
This is the best I got: https://www.youtube.com/watch?v=LOvqdlDbkBs
It worked by rewriting the expression tree so that the blend arguments become sibling nodes and then applying the blend to the union/intersection that is their parent.
That works every time if you only want 1 single targeted blend, but if you want several of them then you can run into unsatisfiable cases where the same object needs to blended with several others and can't be siblings of all of them.
So I gave up :(. For me, CAD without fillets and chamfers is no CAD at all.
(Also, apropos for this thread: the discontinuity in the chamfer was a floating point precision problem...)
Re: It's OK to compare floating-points for equality
#139I have this floating-point problem at scale and will donate $100 to the author, or to anyone here, who can improve my code the most. The Rust code in the assert_f64_eq macro is: if (a >= b && a - b I'm the author of the Rust assertables crate. It provides floating-point assert macros much as described in the article. https://github.com/SixArm/assertables-rust-crate/blob/main/s... If there's a way to make it more prec…
I suggest if a.abs()+b.abs() >= (a-b).abs() * 2f64.powi(48) It remains accurate for small and for big numbers. 48 is slightly less than 52.
Re: It's OK to compare floating-points for equality
#140I have this floating-point problem at scale and will donate $100 to the author, or to anyone here, who can improve my code the most. The Rust code in the assert_f64_eq macro is: if (a >= b && a - b I'm the author of the Rust assertables crate. It provides floating-point assert macros much as described in the article. https://github.com/SixArm/assertables-rust-crate/blob/main/s... If there's a way to make it more prec…
You want equality? ‘a.to_bits() == b.to_bits()’ Alternatively, use ‘partial_eq’ and fall back to bit equality if it returns None.