Casting double to ulong weirdness

via Digitalmars-d digitalmars-d at puremagic.com
Mon Aug 24 10:47:56 PDT 2015


On Monday, 24 August 2015 at 17:26:12 UTC, Steven Schveighoffer 
wrote:
> On 8/24/15 12:52 PM, "=?UTF-8?B?Ik3DoXJjaW8=?= Martins\" 
> <marcioapm at gmail.com>\"" wrote:
>> I'm posting this here for visibility. This was silently 
>> corrupting our
>> data, and might be doing the same for others as well.
>>
>> import std.stdio;
>> void main() {
>>    double x = 1.2;
>>    writeln(cast(ulong)(x * 10.0));
>>    double y = 1.2 * 10.0;
>>    writeln(cast(ulong)y);
>> }
>>
>> Output:
>> 11
>> 12
>
> Yes. This is part of the issue of floating point. 1.2 cannot be 
> represented accurately.
>
> The second case is done via real, not double, and at compile 
> time (i.e. constant folding). There may be other reasons why 
> this works.
>
> You are better off adding a small epsilon:
>
> writeln(cast(ulong)(x * 10.0 + 0.1));
>
>> to!ulong instead of the cast does the right thing, and is a 
>> viable
>> work-around.
>
> to!ulong likely adds the epsilon, but you'd have to look to be 
> sure.
>
> Note, this is NOT a D problem, this is a problem with floating 
> point. And by problem, I mean feature-that-you-should-avoid :)
>
> -Steve

I am familiar with floating-point representations and their 
pitfalls, and I think that is not the issue here.

The issue I am trying to illustrate is the fact that the same 
exact operation returns different results.
Both operations are x * 10.0, except one of them passes through 
the stack before the cast.

I would expect this to be consistent, as I believe is the case in 
C/C++.


More information about the Digitalmars-d mailing list