Jump to page: 1 2
Thread overview
floating point conversion
Jun 01, 2014
Martin Krejcirik
Jun 01, 2014
bearophile
Jun 01, 2014
Martin Krejcirik
Jun 01, 2014
Qox
Jun 01, 2014
Wanderer
Jun 01, 2014
Famous
Jun 01, 2014
Martin Krejcirik
Jun 01, 2014
Famous
Jun 01, 2014
Famous
Jun 01, 2014
Martin Krejcirik
Jun 02, 2014
Jonathan M Davis
Jun 01, 2014
Famous
Jun 02, 2014
Gary Willoughby
June 01, 2014
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).


If your reply is yes, should
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
June 01, 2014
Martin Krejcirik:

>     float a = 1.23f;
>     double b = to!float("1.23");
>     assert (a == b); // ???
> }
>
> Should the assert fail or not ? (Please reply without trying first).

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

Bye,
bearophile
June 01, 2014
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
June 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.
June 01, 2014
On Sunday, 1 June 2014 at 12:45:26 UTC, bearophile wrote:
> It's a bad question.

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
June 01, 2014
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

June 01, 2014
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
June 01, 2014
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 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 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
}
June 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".
June 01, 2014
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






« First   ‹ Prev
1 2