Live data from Hacker News

It's OK to compare floating-points for equality

lisyarus.github.io

121–130 of 150 posts

Re: It's OK to compare floating-points for equality

#121

Earlier quoted context omitted.

Um, what? You've linked an RFC for Rust, but the CPP Reference article for C++ So yeah, the Rust RFC documents a proposed change, and the C++ reference documents an implemented feature, but you could equally link the C++ Proposal document and the Rust library docs to make the opposite point if you wanted. Rust's https://doc.rust-lang.org/std/primitive.f32.html#method.next... https://doc.rust-lang.org/std/primitive.f3…

Oh, my research was wrong and the line from the RFC doc... >Currently it is not possible to answer the question ‘which floating point value comes after x’ in Rust without intimate knowledge of the IEEE 754 standard. So nevermind on it not being present in Rust I guess I was finding old documentation

Yeah, the RFC is explaining what they proposed in 2021. In 2022 that work landed in "nightly" Rust, which means you could see it in the documentation (unless you've turned off seeing unstable features entirely) but to actually use it in software you need the nightly compiler mode and a feature flag in your source #![feature(float_next_up_down)].

By 2025 every remaining question about edge cases or real world experience was resolved and in April 2025 the finished feature was stabilized in release 1.86, so it just works in Rust since about a year.

For future reference you can follow separate links from a Rust RFC document to see whether the project took this RFC (anybody can write one, not everything gets accepted) and then also how far along the implementation work is. Can I use this in nightly? Maybe there's an outstanding question I can help answer. Or, maybe it's writing a stabilization report and this is my last chance to say "Hey, I am an expert on this and your API is a bit wrong".

Re: It's OK to compare floating-points for equality

#122

Earlier quoted context omitted.

Fixed point and Floating point are extremely similar, so most of the time you should just go with floats. If you start with a fixed type, reserve some bits for storing an explicit exponent and define a normalization scheme, you've recreated the core of IEEE floats. That also means we can go the other way and emulate (lower precision) fixed point by masking an appropriate number of LSBs in the significand to regain th…

There are applications where the difference between fixed-point and floating-point numbers matters, i.e. the difference between having a limit for the absolute error or for the relative error. The applications where the difference does not matter are those whose accuracy requirements are much less than provided by the numeric format that is used. When using double-precision FP64 numbers, the rounding errors are frequ…

The core of my multiplayer arena game is in fixed point

I wanted absolute certainty that the rollback netcode would result in identical simulations on any platform, and integer math provides that. With set of wrapper functions and look up tables for trig it’s not that much worse than using regular floats

I am still uncertain if I actually would have been fine with floats, being diligent to round frequently and staying within true integer representable range… but now at least I’m far less afraid of game desyncs and it wasn’t that much work

Cross platform, cross USA games have been stable and fun to play, no fixed point complaints here

Re: It's OK to compare floating-points for equality

#123

I've yet to encounter a need for == equality for floating point operations.

Some environments only expose float as the number type, love2d being one I know. Fortunately love is built on LuaJIT, which does support integer math through the built-in ‘ffi’ library.

My multiplayer arena game rounds reasonably-sized floats and compares them in the presentation layer, but uses fixed point integer math in the core rollback simulation

(I believe JS is a similar story, its number can be either int or float with no way to guarantee integer-only math. I never needed to consider the difference outside of currency for webdev, so I’m less sure)

Re: It's OK to compare floating-points for equality

#124
> It's OK to compare floating-points for equality

Unless you use any compiler I write. As a purist, '==' for floats and doubles will be undefined. And by undefined, I mean unrecoverable. And by unrecoverable, I mean they may be able to extract most of the fragments of silicon, aluminum, and dynamic island, and "put you back together again". But you will "think different".

Unless you are comparing references. References are ok.

Re: It's OK to compare floating-points for equality

#125
post #122

Earlier quoted context omitted.

There are applications where the difference between fixed-point and floating-point numbers matters, i.e. the difference between having a limit for the absolute error or for the relative error. The applications where the difference does not matter are those whose accuracy requirements are much less than provided by the numeric format that is used. When using double-precision FP64 numbers, the rounding errors are frequ…

The core of my multiplayer arena game is in fixed point I wanted absolute certainty that the rollback netcode would result in identical simulations on any platform, and integer math provides that. With set of wrapper functions and look up tables for trig it’s not that much worse than using regular floats I am still uncertain if I actually would have been fine with floats, being diligent to round frequently and stayin…

Floating point determinism has been a personal bugbear of mine for a number of years. You still have to be careful, but it's at the point where it's less work than switching to fixed point (cheap as that may be). There are even libraries [0] [1] that implement full reproducibility with negligible overhead. Compilers shipping incorrectly rounded stdlib functions remains an issue, but they're slowly improving. Language level support for float reproducibility is in the C++ pipeline, and already a design consideration on the Rust side. In a decade or so determinism issues might be a distant memory once you've ensured same inputs to the same instructions in the same order.

[0] https://github.com/J-Montgomery/rfloat

[1] https://github.com/sixitbb/sixit-dmath

Re: It's OK to compare floating-points for equality

#126

Earlier quoted context omitted.

This case actually works because for finite numbers of a given sign, the integer bit representations are monotonic with the value due to the placement of the exponent and mantissa fields and the implicit mantissa bit. For instance, 1.0 in IEEE float is 0x3F800000, and the next immediate representable value below it 1.0-e is 0x3F7FFFFF. Signed zero and the sign-magnitude representation is more of an issue, but can be…

I interpreted OP's "bit-cast to integer, strip few least significant bits and then compare for equality" message as suggesting this kind of comparison (Go): func equiv(x, y float32, ignoreBits int) bool { mask := uint32(0xFFFFFFFF) with the sensitivity controlled by ignoreBits, higher values being less sensitive. Supposing y is 1.0 and x is the predecessor of 1.0, the smallest value of ignoreBits for which equiv woul…

Yeah, that's effectively quantization, which will not work for general tolerance checks where you'd convert float similarity to int similarity.

There are cases where the quantization method is useful, hashing/binning floats being an example. Standard similarity checks don't work there because of lack of transitivity. But that's fundamentally a different operation than is-similar.

Re: It's OK to compare floating-points for equality

#127

> In reality it is a pretty deterministic (modulo compiler options, CPU flags, etc) IIRC this was not ALWAYS the case, on x86 not too long ago the CPU might choose to put your operation in an 80-bit fp register, and if due to multitasking the CPU state got evicted, it would only be able to store it in a 32-bit slot while it's waiting to be scheduled back in? It might not be the case now in a modern system if based on…

This is the kind of misinformation that makes people more wary of floats than they should be. The same series of operations with the same input will always produce exactly the same floating point results. Every time. No exceptions. Hardware doesn't matter. Breed of CPU doesn't matter. Threads don't matter. Scheduling doesn't matter. IEEE floating point is a standard. Everyone follows the standard. Anything not produc…

IEEE standard prescribes 1 ulp precision for some higher operations (trig ops etc). 0.5 ulp does guarantee identical results, but not 1

Re: It's OK to compare floating-points for equality

#128
post #93

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.

Why is that NaN handling sensible? I don't think it makes sense to say log(-1) equals log(-2). Mathematically it isn't true and your implementation would say it's true only because of limitations in IEEE754.

Re: It's OK to compare floating-points for equality

#130

If you need equality, just use fixed point

I agree that using fixed point in many cases is a better option. But floating point is assumed to be the default choice for computations with non-integer numbers, because almost all popular programming languages have only floating-point built-in types, but not fixed point types.
Post reply on HN