Thread overview | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 07, 2015 Fun with floating point | ||||
---|---|---|---|---|
| ||||
Hi, D community! I have this program: import std.stdio; import std.conv; int main(string[] argv) { float eps = 1.0f; float f = 0.0f; while (f + eps != f) f += 1.0f; writeln("eps = " ~ to!string(eps) ~ ", max_f = " ~ to!string(f)); return 0; } According to the languge specification what result would you expect from its execution? When running similar C++ program (VS 2013) the loop terminates and I get t = 2^24 = 16777216. Does D language specifies that loop will be terminated for this program or ? I compiled with DMD and it hungs. Details about assembly generated by DMD can be found here: http://stackoverflow.com/questions/28380651/floating-point-maxing-out-loop-doesnt-terminate-in-d-works-in-c Thanks. |
February 07, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenny | And sory for the typos, cannot find edit functionality here.. |
February 07, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenny | The above code snippet works correctly when I use LDC compiler (it finds expected 'f' value and prints it to console). I'm wondering is it a bug in DMD? p.s. the final code used by both compilers: import std.stdio; import std.conv; int main(string[] argv) { const float eps = 1.0f; float f = 0.0f; while (f + eps != f) f += 1.0f; writeln("eps = ", eps, ", max_f = ", f); return 0; } |
February 07, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenny | To answer your other question, there is no Edit because this is a newsgroup (see NNTP). The forum interface is supposed to be a convenience but it hides that fact. On 02/07/2015 01:33 PM, Kenny wrote: > The above code snippet works correctly There is no right or wrong when you compare floating point values for equality (and inequality) unless those values can be represented exactly in the machine. 1.0 is famously not representable exactly. (It is similar to how 1/3 cannot be represented in the decimal system.) > when I use LDC compiler (it finds > expected 'f' value and prints it to console). I'm wondering is it a bug > in DMD? Not a bug. Ali > > p.s. the final code used by both compilers: > > import std.stdio; > import std.conv; > > int main(string[] argv) > { > const float eps = 1.0f; > float f = 0.0f; > while (f + eps != f) > f += 1.0f; > > writeln("eps = ", eps, ", max_f = ", f); > return 0; > } > > |
February 07, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Saturday, 7 February 2015 at 22:46:56 UTC, Ali Çehreli wrote:
> 1.0 is famously not representable exactly.
1.0 is representable exactly, though.
|
February 07, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenny | On Saturday, 7 February 2015 at 21:33:51 UTC, Kenny wrote:
> The above code snippet works correctly when I use LDC compiler (it finds expected 'f' value and prints it to console). I'm wondering is it a bug in DMD?
>
> p.s. the final code used by both compilers:
>
> import std.stdio;
> import std.conv;
>
> int main(string[] argv)
> {
> const float eps = 1.0f;
> float f = 0.0f;
> while (f + eps != f)
> f += 1.0f;
>
> writeln("eps = ", eps, ", max_f = ", f);
> return 0;
> }
Intermediate calculations may be performed at higher precision than the precision of the values themselves. In particular, the f + eps may be performed with 80 bits of precision, even though both values are 32-bit. The comparison will then fail.
The reason for the difference between DMD and LDC is that DMD tends to use the FPU more with 80 bits of precision, whereas LDC and GDC will use the SSE2 instructions, which only support 32-bit and 64-bit precision.
|
February 07, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Saturday, 7 February 2015 at 23:06:15 UTC, anonymous wrote:
> On Saturday, 7 February 2015 at 22:46:56 UTC, Ali Çehreli wrote:
>> 1.0 is famously not representable exactly.
>
> 1.0 is representable exactly, though.
I think he meant 0.1 :-)
|
February 07, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenny | On 02/07/2015 01:33 PM, Kenny wrote:
> The above code snippet works correctly when I use LDC compiler (it finds
> expected 'f' value and prints it to console). I'm wondering is it a bug
> in DMD?
>
> p.s. the final code used by both compilers:
>
> import std.stdio;
> import std.conv;
>
> int main(string[] argv)
> {
> const float eps = 1.0f;
> float f = 0.0f;
> while (f + eps != f)
> f += 1.0f;
>
> writeln("eps = ", eps, ", max_f = ", f);
> return 0;
> }
>
>
OK, ignore some of my earlier response. :)
The code above works with dmd git head 64-bit compilation and prints the following:
eps = 1, max_f = 1.67772e+07
You can use the %a format specifier when debugging this issue. It allows you see the bits of the floating point value:
writefln("eps: %a", 0.1);
double 0.1 on my system:
eps: 0x1.999999999999ap-4
Ali
|
February 08, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenny | On Saturday, 7 February 2015 at 16:06:14 UTC, Kenny wrote:
> Hi, D community!
>
> I have this program:
>
> import std.stdio;
> import std.conv;
>
> int main(string[] argv)
> {
> float eps = 1.0f;
> float f = 0.0f;
> while (f + eps != f)
> f += 1.0f;
>
> writeln("eps = " ~ to!string(eps) ~ ", max_f = " ~
> to!string(f));
> return 0;
> }
>
> According to the languge specification what result would you
> expect from its execution?
>
> When running similar C++ program (VS 2013) the loop terminates
> and I get t = 2^24 = 16777216.
>
> Does D language specifies that loop will be terminated for this
> program or ?
>
> I compiled with DMD and it hungs.
> Details about assembly generated by DMD can be found here:
> http://stackoverflow.com/questions/28380651/floating-point-maxing-out-loop-doesnt-terminate-in-d-works-in-c
>
> Thanks.
A point of advice that Walter gives for situations like these is to ensure that your algorithm has a minimum required precision to work correctly but not a maximum. As Peter Alexander mentioned, DMD performs intermediate calculations at higher precision than GDC/LDC and thus your algorithm breaks.
|
February 08, 2015 Re: Fun with floating point | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kenny Attachments: | On Sat, 07 Feb 2015 21:33:46 +0000, Kenny wrote:
> The above code snippet works correctly when I use LDC compiler (it finds expected 'f' value and prints it to console). I'm wondering is it a bug in DMD?
nope, this is a bug in your code. compiler (by the specs) is free to perform intermediate calculations with any precision that is not lower than a highest used type (i.e. not lower that `float`'s one for `while` condition (`f + eps != f`). it may be even infinite precision, so your code may not exit the loop at all.
|
Copyright © 1999-2021 by the D Language Foundation