Always false float comparisons
Joseph Rushton Wakeling via Digitalmars-d
digitalmars-d at puremagic.com
Mon May 16 03:14:37 PDT 2016
On Monday, 16 May 2016 at 08:52:16 UTC, Ola Fosheim Grøstad wrote:
> On Monday, 16 May 2016 at 08:47:03 UTC, Iain Buclaw wrote:
>> But you *didn't* request coercion to 32 bit floats. Otherwise
>> you would have used 1.30f.
>
> const float f = 1.3f;
> float c = f;
> assert(c*1.0 == f*1.0); // Fails! SHUTDOWN!
IIRC, there are circumstances where you can get an equality
failure even for non-compile-time calculations that superficially
look identical: e.g. if one of the sides of the comparison is
still stored in one of the 80-bit registers used for calculation.
I ran into this when doing some work in std.complex ... :-(
Reworking Ola's example:
import std.stdio : writefln, writeln;
const float constVar = 1.3f;
float var = constVar;
writefln("%.64g", constVar);
writefln("%.64g", var);
writefln("%.64g", constVar * 1.0);
writefln("%.64g", var * 1.0);
writefln("%.64g", 1.30 * 1.0);
writefln("%.64g", 1.30f * 1.0);
... produces:
1.2999999523162841796875
1.2999999523162841796875
1.3000000000000000444089209850062616169452667236328125
1.2999999523162841796875
1.3000000000000000444089209850062616169452667236328125
1.3000000000000000444089209850062616169452667236328125
... which is unintuitive, to say the least; the `f` qualifier on
the manifest constant being assigned to `const float constVar` is
being completely ignored for the purposes of the multiplication
by 1.0.
In other words, the specified precision of floating-point values
is being ignored for calculations performed at compile-time,
regardless of how much you "qualify" what you want.
More information about the Digitalmars-d
mailing list