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.

Reply via email to