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