Hacker News new | ask | show | jobs
by numlock86 1936 days ago
Ok, so what's true? -0<+0 or -0==+0
3 comments

You can look these things up for yourself - they're standardised in most language's implementations in something called IEEE 754. In the cases you've asked about they're false and true. Is this what you want in all cases? No. Is this what you want in some cases? Yes. It's a tradeoff. You can still observe the difference by dividing by zero (which should be another indication that these aren't real numbers as we're conventionally understand them.)
> they're standardised in most language's implementations in something called IEEE 754

There is the IEEE 754, and there is the language's standard. One should always look at the latter because it's often the case that the language doesn't fully conform to IEEE 754.

You shouldn't really use equality on floating point numbers, except on very special circumstances (and I imagine the == behavior for 0 breaks things more often than it helps). But the wikipedia page on -0 has your case covered:

> According to the IEEE 754 standard, negative zero and positive zero should compare as equal with the usual (numerical) comparison operators, like the == operators of C and Java. In those languages, special programming tricks may be needed to distinguish the two values

> You shouldn't really use equality on floating point numbers, except on very special circumstances.

This is very common advice, so common that it gets cargo-culted into situations where it is really quite poor.

Information storage, retrieval, and transmission systems should faithfully deliver floating-point values that are good to the last bit. Round-trips through databases, transmission over network protocols, etc should all give values back that are exactly identical to what was put into them.

Oh, sure. But those applications should also not use the floating point equality operators. They deal with opaque data, and should make sure not to corrupt it.

Keep in mind that the ISO standard does require that floating point equality tests return false for values that have the exact same binary representation, and that not everything adheres to it and some environments may give you false for identical values even when the standard says it should be true. Also, != is not the negation of == for floating point. So even using those operators to test a round trip over those applications is iffy.

By "the last bit" do you mean the 32nd bit or the 64th bit? :-)

Many times I've tracked down the place in our stack where a double-precision value from user input accidentally goes through a single-precision variable in some C code somewhere and crashes some Python code later on because the values don't match "to the last bit" in the way that the programmer thought... But that's a bug in the C code - I agree completely the the system SHOULD give the value back that was put into it!

This is actually exactly what I mean. Its probably the most common bug I've come across in this class. I don't expect unit tests to capture all rounding bugs (say, due to serialization and de-serialization through text). But I do expect to capture gross errors, such as an inadvertent cast to lower-precision somewhere in the pipeline.

I've worked with highly experienced and accomplished software engineers that expected interchange through protobuf or sql to be inaccurate due to rounding. No! If you stick a finite number in, you should get the exact same finite number back out again. Direct equality is fine for most cases. The sign bit of zero and NaN should also be returned faithfully and tested using memcmp when required.

IMO, the payload bits of NaN should also be also returned faithfully, but too many systems in common practice drop them.

> Round-trips through databases, transmission over network protocols, etc should all give values back that are exactly identical to what was put into them.

Yes that's true... but what's that got to do with using an equality operator?

IEEE 754 also defines a total order of all fp values, where -0.0 immediately precedes 0.0
They're equal. But, copysign(1.0, -0.0) == -1.0