Why were uninitialized floating-point variables changed to quiet NaN's in v2.087?
FinalEvilution
FinalEvilution at gmail.com
Wed Jul 1 18:22:05 UTC 2026
Thank you for making the GitHub issue.
On Wednesday, 1 July 2026 at 11:49:42 UTC, Richard (Rikki) Andrew
Cattermole wrote:
> ```d
> float f;
>
> assert(f is float.init);
> ```
>
> That will fail.
>
> A signally NaN is a different value from a Quiet NaN and is
> expression is a bit wise compare.
>
> Errr that should be float.nan not float.init.
Nether `assert(f is float.init)` or `assert(f is float.nan)` fail
as
```
float f;
float.init;
float.nan;
```
are all
2143289344
2143289344
2143289344
Pre v2.087 this was
2141192192
2141192192
2143289344
which meant you could catch this or more complex examples at
runtime using fp exceptions.
```
// This will generate a hardware exception, if x is a
// default-initialized floating point variable:
float x; // Add `= 0` or even `= real.nan` to not throw the
exception.
float y = x * 3.0;
```
Walter said in the pull request
> They should have the same bit patterns. We tried to make .init
> a signalling nan, but this was a complete failure. .init and
> .nan should both be a quiet nan.
> Because a signalling nan converts to a quiet nan when used. The
> problem was nobody could come up with a consistent definition
> of "used".
Presumably this could cause problems if a signalling nan should
thrown on an op, but then only being
thrown later or not at all, but with FloatingPointControl being
scope local you'd still get help checking
for fp exceptions only where you'd want help checking for one.
I'm just not experienced enough with floating point programming
to know what the problems would be.
More information about the Digitalmars-d-learn
mailing list