Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
November 18, 2019 Strange double to uint conversion | ||||
---|---|---|---|---|
| ||||
Hello, everyone! I'm a new D fan, still learning the language and this is my first post. I came up with a strange behavior, using D 2.089 for windows. Considering the program "error.d": import std.stdio; import std.conv; void main() { uint c(double v) { return (37.05*100.0).to!uint; } double f; uint c2(double v) { return (37.05*f).to!uint; } f=100.0; writeln("All should be 3705, right? -- ", 37.05*100, "; ", 37.05*100.0, "; ", (37.05*100).to!uint, "; ",c(37.05),"; ",c2(37.05)); } I expect all values to be 3705, yet running it with '/c/D/dmd-2.089.0/windows/bin/dmd.exe -run error.d' gives me the output: All should be 3705, right? -- 3705; 3705; 3705; 3705; 3704 I also played with several compilation options, all yelding the same results: dmd -boundscheck=on -m64 -lowmem -of="error" "error".d && ./error dmd -boundscheck=off -m64 -lowmem -of="error" "error".d && ./error dmd -boundscheck=on -m32 -lowmem -of="error" "error".d && ./error dmd -release -O -mcpu=native -boundscheck=on -m64 -lowmem -of="error" "error".d && ./error dmd -release -O -mcpu=native -boundscheck=on -m64 -of="error" "error".d && ./error dmd -of="error" "error".d && ./error What am I doing wrong? |
November 18, 2019 Re: Strange double to uint conversion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luiz Silveira | On Monday, 18 November 2019 at 21:08:39 UTC, Luiz Silveira wrote: > double f; If this is changed to `real f;`, you get the desired result. real is also the type used for the comparison code: https://dlang.org/spec/float.html#fp_const_folding |
November 18, 2019 Re: Strange double to uint conversion | ||||
---|---|---|---|---|
| ||||
Posted in reply to mipri | On Monday, 18 November 2019 at 21:14:37 UTC, mipri wrote:
>> double f;
>
> If this is changed to `real f;`, you get the desired result.
>
> real is also the type used for the comparison code:
> https://dlang.org/spec/float.html#fp_const_folding
Yes, it worked as expected.
Thank you,
Luiz.
|
November 18, 2019 Re: Strange double to uint conversion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luiz Silveira | On 11/18/19 4:08 PM, Luiz Silveira wrote:
> Hello, everyone!
>
> I'm a new D fan, still learning the language and this is my first post.
>
> I came up with a strange behavior, using D 2.089 for windows.
>
> Considering the program "error.d":
>
> import std.stdio;
> import std.conv;
>
> void main() {
> uint c(double v) {
> return (37.05*100.0).to!uint;
> }
>
> double f;
> uint c2(double v) {
> return (37.05*f).to!uint;
> }
> f=100.0;
>
> writeln("All should be 3705, right? -- ", 37.05*100, "; ", 37.05*100.0, "; ", (37.05*100).to!uint, "; ",c(37.05),"; ",c2(37.05));
> }
>
> I expect all values to be 3705, yet running it with '/c/D/dmd-2.089.0/windows/bin/dmd.exe -run error.d' gives me the output:
>
> All should be 3705, right? -- 3705; 3705; 3705; 3705; 3704
>
> I also played with several compilation options, all yelding the same results:
>
> dmd -boundscheck=on -m64 -lowmem -of="error" "error".d && ./error
> dmd -boundscheck=off -m64 -lowmem -of="error" "error".d && ./error
> dmd -boundscheck=on -m32 -lowmem -of="error" "error".d && ./error
> dmd -release -O -mcpu=native -boundscheck=on -m64 -lowmem -of="error" "error".d && ./error
> dmd -release -O -mcpu=native -boundscheck=on -m64 -of="error" "error".d && ./error
> dmd -of="error" "error".d && ./error
>
> What am I doing wrong?
You are expecting floating point to behave as if it is stored as a decimal number. It's not.
An interesting thing is that 5/100 (or 1/20) is not accurately representable in floating point. So you get an approximation in some cases (actually in all cases), but happens to print the right thing.
What you may want to do is use std.math.ceil.
-Steve
|
November 18, 2019 Re: Strange double to uint conversion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 11/18/19 4:54 PM, Steven Schveighoffer wrote:
> What you may want to do is use std.math.ceil.
Sorry, what you want is std.math.round.
-Steve
|
November 19, 2019 Re: Strange double to uint conversion | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 18 November 2019 at 21:54:53 UTC, Steven Schveighoffer wrote:
> You are expecting floating point to behave as if it is stored as a decimal number. It's not.
I was actually asking why 'c' and 'c2' functions behave differently. After mipri's answer I learned that the default floating point representation for literals in D is 'real', not 'double', as in C++.
Changing the type to real resolves the different behavior I was observing.
Just out of curiosity: in C++ a similar code also issues 3704 -- but the same value is returned by 'c' and 'c2', hence my doubt. Using, in C++, 'long double' and suffixing all floating point literals with 'l' gave me the same results as my "fixed" D code.
But, yes, thanks for clarifying about math.round.
|
Copyright © 1999-2021 by the D Language Foundation