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\" <[email protected]>\"" 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++.

Reply via email to