## digitalmars.D.learn - Float Comparison Returns False

• Loopback (40/40) Jul 07 2011 Hello!
• Simen Kjaeraas (15/55) Jul 07 2011 Try adding this in there:
• Steven Schveighoffer (8/48) Jul 07 2011 Because they aren't. Just because they are equal to 5 decimal places
• bearophile (8/18) Jul 07 2011 If you want to use floating point values in your programs then you proba...
• Jonathan M Davis (4/27) Jul 07 2011 What Every Computer Scientist Should Know About Floating-Point Arithmeti...
• Loopback (10/28) Jul 07 2011 I've looked up both approxEqual and feqrel, and the last one seems most
• Loopback (20/58) Jul 09 2011 I weren't able to solve this error so if it's of anyone's interest I
• bearophile (4/6) Jul 09 2011 If you think you have found a bug in Phobos, then I suggest you to add i...
Loopback <elliott.darfink gmail.com> writes:
```Hello!

I've been programming some miscellaneous code and got stuck in an odd
case. While comparing floats, two obviously identical values return
false in comparison.

I am not sure if this is related to float precision or something
similar. This is the code that I have used:

import std.stdio;

void main(string[] args)
{
while(foo()) {}
}

bool foo()
{
static bool ss;
static int loops;
static float m = 0f;

if(m != 1.73205f)
{
m += 0.00500592f;

if(++loops == 346)
ss = true;
}

if(ss)
{
writefln("Variable: %s", m);
writefln("Constant: %s", 1.73205f);
writefln("Equality: %s", m == 1.73205f);

return false;
}

return true;
}

The output of this program is the following:

Variable: 1.73205
Constant: 1.73205
Equality: false

My question is; how come these values compare unequal?
```
Jul 07 2011
"Simen Kjaeraas" <simen.kjaras gmail.com> writes:
```On Thu, 07 Jul 2011 20:19:05 +0200, Loopback <elliott.darfink gmail.com>
wrote:

Hello!

I've been programming some miscellaneous code and got stuck in an odd
case. While comparing floats, two obviously identical values return
false in comparison.

I am not sure if this is related to float precision or something
similar. This is the code that I have used:

import std.stdio;

void main(string[] args)
{
while(foo()) {}
}

bool foo()
{
static bool ss;
static int loops;
static float m = 0f;

if(m != 1.73205f)
{
m += 0.00500592f;

if(++loops == 346)
ss = true;
}

if(ss)
{
writefln("Variable: %s", m);
writefln("Constant: %s", 1.73205f);
writefln("Equality: %s", m == 1.73205f);

return false;
}

return true;
}

The output of this program is the following:

Variable: 1.73205
Constant: 1.73205
Equality: false

My question is; how come these values compare unequal?

writefln("Difference: %s", m - 1.73205);

It prints:
Difference: 1.61095e-06

It may also be worth using %a to see the actual values in a float:

writefln("Variable: %a", m);
writefln("Constant: %a", 1.73205f);

Variable: 0x1.bb67bcp+0
Constant: 0x1.bb67ap+0

As you can see, these numbers are different. Floating point math
is weird. Two numbers that look the same can be different.
--
Simen
```
Jul 07 2011
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```On Thu, 07 Jul 2011 14:19:05 -0400, Loopback <elliott.darfink gmail.com>
wrote:

Hello!

I've been programming some miscellaneous code and got stuck in an odd
case. While comparing floats, two obviously identical values return
false in comparison.

I am not sure if this is related to float precision or something
similar. This is the code that I have used:

import std.stdio;

void main(string[] args)
{
while(foo()) {}
}

bool foo()
{
static bool ss;
static int loops;
static float m = 0f;

if(m != 1.73205f)
{
m += 0.00500592f;

if(++loops == 346)
ss = true;
}

if(ss)
{
writefln("Variable: %s", m);
writefln("Constant: %s", 1.73205f);
writefln("Equality: %s", m == 1.73205f);

return false;
}

return true;
}

The output of this program is the following:

Variable: 1.73205
Constant: 1.73205
Equality: false

My question is; how come these values compare unequal?

Because they aren't.  Just because they are equal to 5 decimal places
(which by the way is an inaccurate printout of their value), does not mean
they are fully equal.

Be very careful when comparing floating point numbers.  Generally you want
to use an epsilon to say they are "close enough".

-Steve
```
Jul 07 2011
Loopback <elliott.darfink gmail.com> writes:
```On 2011-07-07 20:35, Steven Schveighoffer wrote:
On Thu, 07 Jul 2011 14:19:05 -0400, Loopback <elliott.darfink gmail.com>
wrote:

Hello!

I've been programming some miscellaneous code and got stuck in an odd
case. While comparing floats, two obviously identical values return
false in comparison.

I am not sure if this is related to float precision or something
similar. This is the code that I have used:

import std.stdio;

void main(string[] args)
{
while(foo()) {}
}

bool foo()
{
static bool ss;
static int loops;
static float m = 0f;

if(m != 1.73205f)
{
m += 0.00500592f;

if(++loops == 346)
ss = true;
}

if(ss)
{
writefln("Variable: %s", m);
writefln("Constant: %s", 1.73205f);
writefln("Equality: %s", m == 1.73205f);

return false;
}

return true;
}

The output of this program is the following:

Variable: 1.73205
Constant: 1.73205
Equality: false

My question is; how come these values compare unequal?

Because they aren't. Just because they are equal to 5 decimal places
(which by the way is an inaccurate printout of their value), does not
mean they are fully equal.

Be very careful when comparing floating point numbers. Generally you
want to use an epsilon to say they are "close enough".

-Steve

I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
"epsilons" but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.

From what I can see these are two identical values, I would be more than
glad if someone could explain just what is the difference between these
two "non-equal" values and how make them "equal". Perhaps I should use
ints and long instead since they don't seem to suffer from this
"problem"?
```
Jul 07 2011
bearophile <bearophileHUGS lycos.com> writes:
```Loopback:

I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
"epsilons" but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.

If you want to use floating point values in your programs then you probably
need to know something about floating point representation. This is a good
starting point:
http://en.wikipedia.org/wiki/Floating_point
For your problem there is the feqrel function:
http://www.digitalmars.com/d/2.0/phobos/std_math.html#feqrel

From what I can see these are two identical values, I would be more than
glad if someone could explain just what is the difference between these
two "non-equal" values and how make them "equal". Perhaps I should use
ints and long instead since they don't seem to suffer from this
"problem"?

Generally in a program you use floating point values only if you can't use
integral values (and you don't want to go toward fixed point values, rationals,
etc).

Bye,
bearophile
```
Jul 07 2011
"Jonathan M Davis" <jmdavisProg gmx.com> writes:
```On 2011-07-07 17:28, bearophile wrote:
Loopback:
I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
"epsilons" but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.

If you want to use floating point values in your programs then you probably
need to know something about floating point representation. This is a good
starting point: http://en.wikipedia.org/wiki/Floating_point
For your problem there is the feqrel function:
http://www.digitalmars.com/d/2.0/phobos/std_math.html#feqrel

From what I can see these are two identical values, I would be more than

glad if someone could explain just what is the difference between these
two "non-equal" values and how make them "equal". Perhaps I should use
ints and long instead since they don't seem to suffer from this
"problem"?

Generally in a program you use floating point values only if you can't use
integral values (and you don't want to go toward fixed point values,
rationals, etc).

What Every Computer Scientist Should Know About Floating-Point Arithmetic:

- Jonathan M Davis
```
Jul 07 2011
Loopback <elliott.darfink gmail.com> writes:
```On 2011-07-08 02:28, bearophile wrote:
Loopback:

I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
"epsilons" but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.

If you want to use floating point values in your programs then you probably
need to know something about floating point representation. This is a good
starting point:
http://en.wikipedia.org/wiki/Floating_point
For your problem there is the feqrel function:
http://www.digitalmars.com/d/2.0/phobos/std_math.html#feqrel

From what I can see these are two identical values, I would be more than
glad if someone could explain just what is the difference between these
two "non-equal" values and how make them "equal". Perhaps I should use
ints and long instead since they don't seem to suffer from this
"problem"?

Generally in a program you use floating point values only if you can't use
integral values (and you don't want to go toward fixed point values, rationals,
etc).

Bye,
bearophile

I've looked up both approxEqual and feqrel, and the last one seems most
appropriate, though I cannot use this function without issuing any
errors. If I use the following code:

writefln("Equality: %s", feqrel(m, 1.73205f));

(From the previous example)

I receive this error with the code:
Error: function std.math.feqrel!(float).feqrel has no return statement,
but is expected to return a value of type int
Error: template instance std.math.feqrel!(float) error instantiating
```
Jul 07 2011
Loopback <elliott.darfink gmail.com> writes:
```On 2011-07-08 04:31, Loopback wrote:
On 2011-07-08 02:28, bearophile wrote:
Loopback:

I do want to ask though what an alternative would be in this case, to
compare the two different values. You mentioned something about
"epsilons" but I have no experience within this field. I would really
appreciate an example or something similar so I could understand your
statement.

If you want to use floating point values in your programs then you
probably need to know something about floating point representation.
This is a good starting point:
http://en.wikipedia.org/wiki/Floating_point
For your problem there is the feqrel function:
http://www.digitalmars.com/d/2.0/phobos/std_math.html#feqrel

From what I can see these are two identical values, I would be more than
glad if someone could explain just what is the difference between these
two "non-equal" values and how make them "equal". Perhaps I should use
ints and long instead since they don't seem to suffer from this
"problem"?

Generally in a program you use floating point values only if you can't
use integral values (and you don't want to go toward fixed point
values, rationals, etc).

Bye,
bearophile

I've looked up both approxEqual and feqrel, and the last one seems most
appropriate, though I cannot use this function without issuing any
errors. If I use the following code:

writefln("Equality: %s", feqrel(m, 1.73205f));

(From the previous example)

I receive this error with the code:
Error: function std.math.feqrel!(float).feqrel has no return statement,
but is expected to return a value of type int
Error: template instance std.math.feqrel!(float) error instantiating

I weren't able to solve this error so if it's of anyone's interest I

int feqrel(real a, real b)
{
if (a==b) return real.mant_dig;
real diff = fabs(a-b);

ushort *pa = cast(ushort *)(&a);
ushort *pb = cast(ushort *)(&b);
ushort *pd = cast(ushort *)(&diff);

int bitsdiff = ( ((pa[4]&0x7FFF) + (pb[4]&0x7FFF)-1)>>1) - pd[4];

if (pd[4]== 0)
{
diff*=0x1p+63;
return bitsdiff + real.mant_dig - pd[4];
}
if (bitsdiff>0) return bitsdiff+1;
return bitsdiff==0 ? pa[4]==pb[4] : 0;
}

From: http://www.digitalmars.com/d/archives/digitalmars/D/27873.html
```
Jul 09 2011
bearophile <bearophileHUGS lycos.com> writes:
```Loopback:

I weren't able to solve this error so if it's of anyone's interest I

If you think you have found a bug in Phobos, then I suggest you to add it to
Bugzilla (with your working version too, if you want).

Bye,
bearophile
```
Jul 09 2011
```This has already been reported:
http://d.puremagic.com/issues/show_bug.cgi?id=5089

David

On 7/9/11 2:01 PM, bearophile wrote:
Loopback:

I weren't able to solve this error so if it's of anyone's interest I