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.
- Martin Krejcirik (10/12) Jun 01 2014 void main()
- Famous (21/33) Jun 01 2014 This is different. The decimal 1.234 cannot be exacly represented
- Famous (8/8) Jun 01 2014 I have compiled some cases at
- Martin Krejcirik (7/10) Jun 01 2014 Still feels iffy to me. If you add:
- Jonathan M Davis via Digitalmars-d-learn (15/21) Jun 01 2014 On Sun, 01 Jun 2014 14:42:34 +0000
- 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
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
Jun 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
Jun 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
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
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
Jun 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
Jun 01 2014
On Sunday, 1 June 2014 at 15:31:53 UTC, Martin Krejcirik wrote:On 1.6.2014 16:42, 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 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 }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 ?
Jun 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
Jun 01 2014
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 isStill 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
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: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 DavisIt'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.
Jun 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
Jun 01 2014
I have a couple of functions that you may find useful for comparing floats. https://github.com/nomad-software/dunit/blob/master/source/dunit/toolkit.d#L42 https://github.com/nomad-software/dunit/blob/master/source/dunit/toolkit.d#L134
Jun 02 2014