Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
January 26, 2008 type comparisons | ||||
---|---|---|---|---|
| ||||
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); } |
January 26, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | 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.
|
January 26, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to BCS | On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:
> Reply to Denton,
>
>> [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
|
January 26, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | Denton Cockburn wrote:
> On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote:
>
>> Reply to Denton,
>>
>>> [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.
Instead do something like
assert(abs(c-a) < rounding_tolerance);
--bb
|
January 26, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn Attachments: | Denton Cockburn wrote: > On Sat, 26 Jan 2008 18:36:41 +0000, BCS wrote: > >> Reply to Denton, >> >>> [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 | +---------------------------------+------------------------------+ |
January 26, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jérôme M. Berger | 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:
> >
> >> Reply to Denton,
> >>
> >>> [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.
|
January 26, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | 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:
>>>
>>>> Reply to Denton,
>>>>
>>>>> [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
|
January 28, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | "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 Skip to the section on Accuracy. 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 |
January 28, 2008 Re: type comparisons | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | "Steven Schveighoffer" wrote
> 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)
Er... this should be:
assert(x - myError > y)
-Steve
|
Copyright © 1999-2021 by the D Language Foundation