Disallow (dis)equality with FP.nan/FP.init literals

so so at so.so
Wed Apr 18 18:28:50 PDT 2012


On Thursday, 19 April 2012 at 00:50:09 UTC, bearophile wrote:
> This is an open enhancement request that I'll probably add to 
> Bugzilla.
> The direct cause of it is a recent discussion in D.learn, but I 
> and other people are aware of this problem for a lot of time.
>
>
> Since a lot of time D statically refuses the use of 
> "classReference == null":
>
> // Program #1
> class Foo {}
> void main() {
>     Foo f;
>     assert(f == null);
>     assert(f != null);
> }
>
>
> test.d(4): Error: use 'is' instead of '==' when comparing with 
> null
> test.d(5): Error: use '!is' instead of '!=' when comparing with 
> null
>
>
>
> A not expert D programmer sometimes compares a double with 
> double.nan in a wrong way:
>
> http://forum.dlang.org/thread/mailman.1845.1334694574.4860.digitalmars-d-learn@puremagic.com#post-jmlhfr:2428cv:241:40digitalmars.com
>
> because someDouble == double.nan is always false:
>
>
> // Program #2
> import std.math: isNaN;
> void main() {
>     double x = double.init;
>     assert(x != double.nan);
>     assert(x != double.init);
>     assert(isNaN(x));
>     assert(x is double.init);
>     assert(x !is double.nan);
>
>     double y = double.nan;
>     assert(y != double.nan);
>     assert(y != double.init);
>     assert(isNaN(y));
>     assert(y !is double.init);
>     assert(y is double.nan);
> }
>
>
>
> I think there are three common wrong usage patterns of NaNs 
> testing:
> 1) Test that x is equal to/different from nan using 
> x==FP.nan/x!=FP.nan
> 2) Test that x is equal to/different from all NaNs using 
> x==FP.nan/x!=FP.nan
> 3) Test that x is equal to/different from FP.init using 
> x==FP.init/x!=FP.init
>
> The case 3 is a bit less important because the programmer 
> already knows something about FP init, but it's wrong still.
>
> There are other wrong usages of NaNs but they are by more 
> expert programmers, to I don't want to catch them (example: 
> using "is" to test if x is equal to/different from all NaNs is 
> a bug, because there are more than one NaN. But if the 
> programmer uses "is" I assume he/she/shi knows enough about 
> NaNs, so this is not flagged by the compiler).
>
> Currently this program compiles with no errors:
>
>
> // Program #3
> void main() {
>     float x1 = float.nan;
>     assert(x1 == float.nan);
>     float x2 = 0.0;
>     assert(x2 != float.nan);
>     float x3 = float.init;
>     assert(x3 == float.init);
>     float x4 = 0.0;
>     assert(x4 != float.init);
>
>     double x5 = double.nan;
>     assert(x5 == double.nan);
>     double x6 = 0.0;
>     assert(x6 != double.nan);
>     double x7 = double.init;
>     assert(x7 == double.init);
>     double x8 = 0.0;
>     assert(x8 != double.init);
>
>     real x9 = real.nan;
>     assert(x9 == real.nan);
>     real x10 = 0.0;
>     assert(x10 != real.nan);
>     real x11 = real.init;
>     assert(x11 == real.init);
>     real x12 = 0.0;
>     assert(x12 != real.init);
>
>     enum double myNaN = double.nan;
>     assert(myNaN == double.nan);
> }
>
>
>
> So I propose to statically disallow comparisons of Program #3, 
> so it generates errors similar to:
>
> test.d(4): Error: comparison is always false. Use 
> 'std.math.isNaN' to test for every kind of NaN or 'is 
> float.nan' for this specific NaN
> test.d(6): Error: comparison is always true. Use 
> '!std.math.isNaN' to test for every kind of NaN or '!is 
> float.nan' for this specific NaN
> test.d(8): Error: comparison is always false. Use 
> 'std.math.isNaN' to test for every kind of NaN or 'is 
> float.init' for this specicif NaN
> ...
>
>
> Opinions, improvements, votes or critics are welcome.
>
> Bye,
> bearophile

Good idea.
But nothing beats this:

int main() {
     double  q;
     q = 3.0/7.0;
     if (q == 3.0/7.0) printf("Equal\n");
     else printf("Not Equal\n");
     return 0;
}

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
Should we disable implicit conversion "at" comparison as well?


More information about the Digitalmars-d mailing list