## digitalmars.D.learn - floating point conversion

• Martin Krejcirik (14/14) Jun 01 2014 import std.conv;
• bearophile (5/11) Jun 01 2014 It's a bad question. Generally to compare floating point values
• Martin Krejcirik (7/9) Jun 01 2014 So it's just a coincidence, that GDC, LDC x86 and also DMD x86_64
• Qox (8/11) Jun 01 2014 (Equality) Compareision of float/float or float/double are
• Wanderer (8/11) Jun 01 2014 That's not exactly true. You cannot (and should not) compare
• Famous (6/7) Jun 01 2014 Actually, Martin's question is a good one.
• Famous (5/5) Jun 01 2014 float a = 1.234f;
• Gary Willoughby (4/4) Jun 02 2014 I have a couple of functions that you may find useful for
Martin Krejcirik <mk-junk i-line.cz> writes:
```import std.conv;

void main()
{
float a = 1.23f;
double b = to!float("1.23");
assert (a == b); // ???
}

Should the assert fail or not ? (Please reply without trying first).

assert (a == to!float("1.23"))
fail or not ?

I'm bringing this up, because dmd and gdc (x86) don't agree on this.

--
mk
```
Jun 01 2014
"bearophile" <bearophileHUGS lycos.com> writes:
```Martin Krejcirik:

float a = 1.23f;
double b = to!float("1.23");
assert (a == b); // ???
}

first).

It's a bad question. Generally to compare floating point values
for equality use std.math.feqrel.

Bye,
bearophile
```
Jun 01 2014
Martin Krejcirik <mk-junk i-line.cz> writes:
```On 1.6.2014 14:45, bearophile wrote:
It's a bad question. Generally to compare floating point values for
equality use std.math.feqrel.

So it's just a coincidence, that GDC, LDC x86 and also DMD x86_64
doesn't fail ?

And this bug https://issues.dlang.org/show_bug.cgi?id=12831
should be marked invalid ?

--
mk
```
Jun 01 2014
``` So it's just a coincidence, that GDC, LDC x86 and also DMD
x86_64
doesn't fail ?

(Equality) Compareision of float/float or float/double are
machine dependent (depends even on x86 on the generated code
(SSE/SSE2/AVX/AVX2), rounding settings, maybe event the cpu
vendor etc.).
On other platforms (ARM, etc) it could be even more weird.

The General rule is not to compare floats for equality, (is
0.0==-0.0, etc.). Use a epsilon based comparision scheme instead
or a wrapper around it.
```
Jun 01 2014
``` The General rule is not to compare floats for equality, (is
0.0==-0.0, etc.). Use a epsilon based comparision scheme
instead or a wrapper around it.

That's not exactly true. You cannot (and should not) compare
floating points for equality, and use epsilon-based comparison
instead, only in one certain case: when one of the arguments if
the result of computation, during which a computational error
might accumulate.

If you have two exact or constant values, comparing them directly
is perfectly fine. :-) Nowadays floating-point hardware support
is not that "buggy".
```
Jun 01 2014
"Famous" <famous review_queue.org> writes:
```On Sunday, 1 June 2014 at 12:45:26 UTC, bearophile wrote:

Actually, Martin's question is a good one.

Initializing a variable of type float via a literal or as
conversion from string should be the same, exacly, always.
Casting a float to double should be deterministic as well.

Famous
```
Jun 01 2014
Martin Krejcirik <mk-junk i-line.cz> writes:
```On 1.6.2014 16:42, Famous wrote:
from string should be the same, exacly, always. Casting a float to
double should be deterministic as well.

void main()
{
float a = 1.234f;
double b = 1.234;
assert (a == cast(float) b); // fails in DMD x86, works in GDC, LDC
}

Maybe enhancement request ?

--
mk
```
Jun 01 2014
"Famous" <famous review_queue.org> writes:
```On Sunday, 1 June 2014 at 15:31:53 UTC, Martin Krejcirik wrote:
On 1.6.2014 16:42, Famous wrote:
from string should be the same, exacly, always. Casting a
float to
double should be deterministic as well.

void main()
{
float a = 1.234f;
double b = 1.234;
assert (a == cast(float) b); // fails in DMD x86, works in
GDC, LDC
}

Maybe enhancement request ?

This is different. The decimal 1.234 cannot be exacly represented
are not equal. They are both approximations to 1.234 but the
value of b is closer. Then casting b to float might or might not
result in the same value as that of a. This is what bearophile
and Qox referred to.

Since every float can be exacly converted to double the following
situation is different:

float a = 1.234f;
double b = a;
assert(a == b);  // always succeeds in a sane environment

When taking into account constant folding, well, decide on your
own, whether the following behaviour is sane:

void main()
{
const float a = 1.234f;
float b = 1.234f;

assert(a == 1.234); // ok
assert(b == 1.234); // fails
}
```
Jun 01 2014
"Famous" <famous review_queue.org> writes:
```I have compiled some cases at

http://dpaste.dzfl.pl/5611b8bce8e3

This implies that floating-point constants do not have fixed but
minimum precision. Particularly, the literal 1.23 describes a
floating-point value with either double or real precision
depending on what it is compared to.

This seems to comply with

http://dlang.org/float.html
```
Jun 01 2014
Martin Krejcirik <mk-junk i-line.cz> writes:
```On 1.6.2014 18:02, Famous wrote:
This is different. The decimal 1.234 cannot be exacly represented as
radix-2 floating-point number. In your example above, a and b are not
equal. They are both approximations to 1.234 but the value of b is

Still feels iffy to me. If you add:

printf("%.70f\n%.70f\n", a, cast(float) b);

you can see that gcc in C and gdc in D both convert value of b to float
resulting in equality. Dmd doesn't, it just ignore the cast.

--
mk
```
Jun 01 2014
Jonathan M Davis via Digitalmars-d-learn writes:
```On Sun, 01 Jun 2014 14:42:34 +0000
Famous via Digitalmars-d-learn <digitalmars-d-learn puremagic.com>
wrote:

On Sunday, 1 June 2014 at 12:45:26 UTC, bearophile wrote:

Actually, Martin's question is a good one.

Initializing a variable of type float via a literal or as
conversion from string should be the same, exacly, always.
Casting a float to double should be deterministic as well.

Not necessarily, particularly because any floating point operations done at
compile time are generally done at much higher precision than those done at
runtime. So, it's pretty trivial for very similar floating point operations to
end up with slightly different results. In general, expecting any kind of
exactness from floating point values is asking for trouble. Sure, they follow
the rules that they have consistently, but there are so many numbers that
aren't actually representable by a floating point value, the precisions vary
just enough, and slightly different code paths can result in slightly
different results that depending on floating point operations resulting in
any kind of specific values except under very controlled circumstances just
isn't going to work.

- Jonathan M Davis
```
Jun 01 2014
"Famous" <famous review_queue.org> writes:
```float a = 1.234f;
float b = to!float("1.234");
assert (a == b);
assert (a == to!float("1.234")); // is allowed to fail due to
constant folding
```
Jun 01 2014
```I have a couple of functions that you may find useful for