## digitalmars.D.learn - type comparisons

Denton Cockburn <diboss hotmail.com> writes:
```Why does this throw these assert errors?
both are thrown.

All 3 - DMD 2.008/2.009/2.010

void main()
{
real x = 0.6584L;
double y = 0.6584;
assert(x == y);
assert(cast(double)x == y);
}
```
Jan 26 2008
```Reply to Denton,

Why does this throw these assert errors?
both are thrown.
All 3 - DMD 2.008/2.009/2.010

void main()
{
real x = 0.6584L;
double y = 0.6584;
assert(x == y);
assert(cast(double)x == y);
}

rounding error?

rounding 0.6584 (base 10) to real and then converting to double may round
different than rounding it directly to double.
```
Jan 26 2008
Denton Cockburn <diboss hotmail.com> writes:
```On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[quoted text muted]

rounding error?

rounding 0.6584 (base 10) to real and then converting to double may round
different than rounding it directly to double.

I can't think of a reason that would be acceptable.
This means I can't reliably do operations with converted reals/doubles :(

This is also weird:
double a = 0.65;
real b = a + 0.1;
b -= 0.1;
assert(b == a); // fails

real c = a;
c += 0.1;
c -= 0.1;
assert(c == a); // passes
```
Jan 26 2008
Bill Baxter <dnewsgroup billbaxter.com> writes:
```Denton Cockburn wrote:
On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[quoted text muted]

rounding error?

rounding 0.6584 (base 10) to real and then converting to double may round
different than rounding it directly to double.

I can't think of a reason that would be acceptable.
This means I can't reliably do operations with converted reals/doubles :(

This is also weird:
double a = 0.65;
real b = a + 0.1;
b -= 0.1;
assert(b == a); // fails

real c = a;
c += 0.1;
c -= 0.1;
assert(c == a); // passes

You should never compare floating point values using ==.  It's not D's
fault, it's the lossy nature of floating point calculations themselves.

assert(abs(c-a) < rounding_tolerance);

--bb
```
Jan 26 2008
=?ISO-8859-1?Q?=22J=E9r=F4me_M=2E_Berger=22?= <jeberger free.fr> writes:
```-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Denton Cockburn wrote:
On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[quoted text muted]

rounding error?

rounding 0.6584 (base 10) to real and then converting to double may round
different than rounding it directly to double.

I can't think of a reason that would be acceptable.
This means I can't reliably do operations with converted reals/doubles :(

This is also weird:
double a = 0.65;
real b = a + 0.1;

Here, you're computing "a + 0.1" using double, then converting it
to real

b -= 0.1;
assert(b == a); // fails

real c = a;
c += 0.1;

Here, you converted a to real, then you add 0.1 using real.

c -= 0.1;
assert(c == a); // passes

Which could explain that rounding errors wind up different and make
one assertion pass while the other fails.

Jerome
- --
+------------------------- Jerome M. BERGER ---------------------+
|    mailto:jeberger free.fr      | ICQ:    238062172            |
|    http://jeberger.free.fr/     | Jabber: jeberger jabber.fr   |
+---------------------------------+------------------------------+
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFHm4y1d0kWM4JG3k8RAgfQAKC3LwsQfklEVT+cP2w3HrR/xtK6JACfdPr9
PQIwRTbf2zyhpst9zdeZn9s=
=RA4Q
-----END PGP SIGNATURE-----
```
Jan 26 2008
Denton Cockburn <diboss hotmail.com> writes:
```Jérôme M. Berger Wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Denton Cockburn wrote:
On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[quoted text muted]

rounding error?

rounding 0.6584 (base 10) to real and then converting to double may round
different than rounding it directly to double.

I can't think of a reason that would be acceptable.
This means I can't reliably do operations with converted reals/doubles :(

This is also weird:
double a = 0.65;
real b = a + 0.1;

Here, you're computing "a + 0.1" using double, then converting it
to real

b -= 0.1;
assert(b == a); // fails

real c = a;
c += 0.1;

Here, you converted a to real, then you add 0.1 using real.

c -= 0.1;
assert(c == a); // passes

Which could explain that rounding errors wind up different and make
one assertion pass while the other fails.

Jerome
- --
+------------------------- Jerome M. BERGER ---------------------+
|    mailto:jeberger free.fr      | ICQ:    238062172            |
|    http://jeberger.free.fr/     | Jabber: jeberger jabber.fr   |
+---------------------------------+------------------------------+
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFHm4y1d0kWM4JG3k8RAgfQAKC3LwsQfklEVT+cP2w3HrR/xtK6JACfdPr9
PQIwRTbf2zyhpst9zdeZn9s=
=RA4Q
-----END PGP SIGNATURE-----

The problem I'm having is that we are comparing the same numerical value for
equality, and getting a (logically) false result.
```
Jan 26 2008
Bill Baxter <dnewsgroup billbaxter.com> writes:
```Denton Cockburn wrote:
Jérôme M. Berger Wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Denton Cockburn wrote:
On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:

[quoted text muted]

rounding error?

rounding 0.6584 (base 10) to real and then converting to double may round
different than rounding it directly to double.

I can't think of a reason that would be acceptable.
This means I can't reliably do operations with converted reals/doubles :(

This is also weird:
double a = 0.65;
real b = a + 0.1;

Here, you're computing "a + 0.1" using double, then converting it
to real

b -= 0.1;
assert(b == a); // fails

real c = a;
c += 0.1;

Here, you converted a to real, then you add 0.1 using real.

c -= 0.1;
assert(c == a); // passes

Which could explain that rounding errors wind up different and make
one assertion pass while the other fails.

Jerome
- --
+------------------------- Jerome M. BERGER ---------------------+
|    mailto:jeberger free.fr      | ICQ:    238062172            |
|    http://jeberger.free.fr/     | Jabber: jeberger jabber.fr   |
+---------------------------------+------------------------------+
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (GNU/Linux)

iD8DBQFHm4y1d0kWM4JG3k8RAgfQAKC3LwsQfklEVT+cP2w3HrR/xtK6JACfdPr9
PQIwRTbf2zyhpst9zdeZn9s=
=RA4Q
-----END PGP SIGNATURE-----

The problem I'm having is that we are comparing the same numerical value for
equality, and getting a (logically) false result.

One tenth is not exactly representable in floating point.  Therefore you
get rounding errors the moment you try to store .1 in a
float/double/real.  real can represent 1/10 a bit more accurately than
double.  So .1 as a double, then cast to a real is not quite the same as
.1 that started as a real.

Try .125 or 0.0625 and you'll get a good answer.  But .1 is bad news for
floating point.

--bb
```
Jan 26 2008
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```"Denton Cockburn" wrote
The problem I'm having is that we are comparing the same numerical value
for equality, and getting a (logically) false result.

This is inherent in floating point.  This happens in other languages as
well.

The problem is that .1 is like 1/3 in decimal.  Decimal cannot accurately
represent 1/3 because it is a repeating decimal (0.3333...).  Likewise,
floating point, which is base-2, cannot represent all decimal values
accurately.

For an in-depth explanation, see http://en.wikipedia.org/wiki/Floating_point

To work correctly, you should always compare floating point values by adding
some small error.  So instead of:

assert(x > y)
you write

const myError = 1e-10;
assert(x + myError > y)

Equality looks something more like:

assert(fabs(x - y) < myError)

-Steve
```
Jan 28 2008
"Steven Schveighoffer" <schveiguy yahoo.com> writes:
```"Steven Schveighoffer" wrote
To work correctly, you should always compare floating point values by

assert(x > y)
you write

const myError = 1e-10;
assert(x + myError > y)

Er... this should be:

assert(x - myError > y)

-Steve
```
Jan 28 2008