Jump to page: 1 2
Thread overview
double.init is nan ..?
Mar 14, 2014
Etienne
Mar 14, 2014
bearophile
Mar 14, 2014
Adam D. Ruppe
Mar 14, 2014
Etienne
Mar 14, 2014
Etienne
Mar 14, 2014
Adam D. Ruppe
Mar 14, 2014
bearophile
Mar 14, 2014
Adam D. Ruppe
Mar 14, 2014
Etienne
Mar 14, 2014
bearophile
Mar 14, 2014
Adam D. Ruppe
Mar 15, 2014
luka8088
March 14, 2014
I'm trying to compare two doubles as part of a cache framework. To put it simply, double.init == double.init ... is false?

I don't understand. Maybe this belongs is D.learn, but I have no idea why or how this could possibly be normal behavior.

Does anyone have a clue? Thanks!
March 14, 2014
Etienne:

> I'm trying to compare two doubles as part of a cache framework. To put it simply, double.init == double.init ... is false?
>
> I don't understand. Maybe this belongs is D.learn, but I have no idea why or how this could possibly be normal behavior.
>
> Does anyone have a clue? Thanks!

Yes, it's a question for D.learn. And double.init is a NaN. NaN comparisons return false.

Bye,
bearophile
March 14, 2014
On Friday, 14 March 2014 at 16:06:17 UTC, bearophile wrote:
> And double.init is a NaN.

Yes, and the reason for this is NaN is similar to null - an invalid state, so it can help you to catch uninitialized variables.

You should explicitly initialize the variables normally and for the cache case, either keep a separate variable to tell if it is initialized (since NaN might be a valid cache state, like how an int may legitimately be 0) or compare using std.math.isNaN.
March 14, 2014
On 2014-03-14 12:10 PM, Adam D. Ruppe wrote:
> On Friday, 14 March 2014 at 16:06:17 UTC, bearophile wrote:
>> And double.init is a NaN.
>
> Yes, and the reason for this is NaN is similar to null - an invalid
> state, so it can help you to catch uninitialized variables.
>
> You should explicitly initialize the variables normally and for the
> cache case, either keep a separate variable to tell if it is initialized
> (since NaN might be a valid cache state, like how an int may
> legitimately be 0) or compare using std.math.isNaN.

The cache library stores serialized strings mostly, and returns an empty value if there's a get on an empty key (like redis), so I was surprised to see get("key").unpack!double == double.init == false even when they key doesn't exist.

So, I guess I'll have to modify msgpack-d to give doubles a 0.000 initialization value!
March 14, 2014
On 2014-03-14 12:14 PM, Etienne wrote:
> On 2014-03-14 12:10 PM, Adam D. Ruppe wrote:
>> On Friday, 14 March 2014 at 16:06:17 UTC, bearophile wrote:
>>> And double.init is a NaN.
>>
>> Yes, and the reason for this is NaN is similar to null - an invalid
>> state, so it can help you to catch uninitialized variables.
>>
>> You should explicitly initialize the variables normally and for the
>> cache case, either keep a separate variable to tell if it is initialized
>> (since NaN might be a valid cache state, like how an int may
>> legitimately be 0) or compare using std.math.isNaN.

Ok isNaN works on the deserialized values and simple comparisons works on the serialized values in the cache store. Struct.init is unreliable now in my books. Thanks!
March 14, 2014
On Friday, 14 March 2014 at 16:25:59 UTC, Etienne wrote:
> Struct.init is unreliable now in my books. Thanks!

Interestingly:

struct A{
        int a;
        double b;
}

void main() {
        A a;
        assert(a is A.init); // passes
        assert(a == A.init); // fails

        double test;
        assert(test is double.nan); // fails
}


I struct == other_struct works basically by checking the equality operator on each member inside.

So that is like saying assert(a.a == A.init.a && b.a ==B.init.b) which fails cuz of the nan rule.


Whereas struct is other_struct works by just comparing the memory bytes, regardless of the types of the contents. If they match, it is considered a pass, which will always be the case for comparing against init.
March 14, 2014
Adam D. Ruppe:

>         double test;
>         assert(test is double.nan); // fails

Keep in mind that there are many NaNs, and double.nan is not the same as dounle init. So this passes:

assert(test is double.init);

Bye,
bearophile
March 14, 2014
On Friday, 14 March 2014 at 16:50:11 UTC, bearophile wrote:
> Keep in mind that there are many NaNs, and double.nan is not the same as dounle init.

Oh yeah, I forgot about that! (double.init is a signaling nan while double.nan is not. There's a whole bunch of other nans possible in floating point too btw)

You're right. Looks like "is" always just compares the raw bits, which is good stuff when comparing with init.

> So this passes:
>
> assert(test is double.init);
March 14, 2014
On 2014-03-14 1:01 PM, Adam D. Ruppe wrote:
> On Friday, 14 March 2014 at 16:50:11 UTC, bearophile wrote:
>> Keep in mind that there are many NaNs, and double.nan is not the same
>> as dounle init.
>
> Oh yeah, I forgot about that! (double.init is a signaling nan while
> double.nan is not. There's a whole bunch of other nans possible in
> floating point too btw)
>
> You're right. Looks like "is" always just compares the raw bits, which
> is good stuff when comparing with init.
>
>> So this passes:
>>
>> assert(test is double.init);

OK so I don't have to pack the structs to compare them! Thanks :)
March 14, 2014
Etienne:

> OK so I don't have to pack the structs to compare them! Thanks :)

"is" between complex values should be seen as a special tool, to be used carefully. It's not a good idea to use it widely and carelessly.

Bye,
bearophie
« First   ‹ Prev
1 2