Simple Math Problem

Can anyone shed some light on a simple math problem I have encountered?
I am doing a very simple calculation, and the comparison of that result
compared to the number itself is returning false in some cases...for
instance:

$irb

v1 = 80.04

=> 80.04

v2 = 0.12 * 667

=> 80.04

v1 == v2

=> false

v1 > v2

=> true

v1 < v2

=> false

v1.inspect

=> "80.04"

v2.inspect

=> "80.04"

Any insight?

Thanks,
Thom

···

--
Posted via http://www.ruby-forum.com/\.

Machine roundoff error. Floating point values are never precise on any computer.

The best way to compare two floating point values is to take there
difference and make sure it lies withing some acceptable error limit.

v1 = 80.04
v2 = 0.12 * 667
diff = v1-v2
diff.abs < Float::EPSILON

That last line returns false, so you need to choose a different epsilon ...

diff.abs < 1.0e-12

That will return true.

Blessings,
TwP

···

On 11/8/06, Thom Loring <tloring@mac.com> wrote:

Can anyone shed some light on a simple math problem I have encountered?
I am doing a very simple calculation, and the comparison of that result
compared to the number itself is returning false in some cases...for
instance:

$irb
>> v1 = 80.04
=> 80.04

>> v2 = 0.12 * 667
=> 80.04

>> v1 == v2
=> false

>> v1 > v2
=> true

>> v1 < v2
=> false

>> v1.inspect
=> "80.04"

>> v2.inspect
=> "80.04"

Any insight?

-a

···

On Thu, 9 Nov 2006, Thom Loring wrote:

Can anyone shed some light on a simple math problem I have encountered?
I am doing a very simple calculation, and the comparison of that result
compared to the number itself is returning false in some cases...for
instance:

$irb

v1 = 80.04

=> 80.04

v2 = 0.12 * 667

=> 80.04

v1 == v2

=> false

v1 > v2

=> true

v1 < v2

=> false

v1.inspect

=> "80.04"

v2.inspect

=> "80.04"

Any insight?

Thanks,
Thom

--
my religion is very simple. my religion is kindness. -- the dalai lama

* Thom Loring, 11/08/2006 06:35 PM:

Any insight?

Visit an introduction to Numerical Mathematics at your favorite
university. Numerical imprecision and the stability of algorithms
against it is one of the most prominent questions addressed there.
Also they address the question how precise a result of a computation
can be given a certain imprecision of input that either results from
the computer's approximation to a given value (decimal 0.1 cannot be
represented as a binary fraction with a finite number of digits) or
from imprecisely known values - which includes any measured quantity
occuring in natural science (actually all quantities that are not
defined by law as it is the case with vacuum light speed that by law
is defined to be precisely 299792458 m/s).

Jupp

brains hgs 226 %> irb
irb(main):001:0> v1 = 80.04
=> 80.04
irb(main):002:0> v2 = 0.12 * 667
=> 80.04
irb(main):003:0> puts "%.20f" % v1
80.04000000000000625278
=> nil
irb(main):004:0> puts "%.20f" % v2
80.03999999999999204192
=> nil
irb(main):005:0> exit
brains hgs 227 %>

        Hugh

···

On Thu, 9 Nov 2006, Tim Pease wrote:

On 11/8/06, Thom Loring <tloring@mac.com> wrote:
> Can anyone shed some light on a simple math problem I have encountered?
> I am doing a very simple calculation, and the comparison of that result
> compared to the number itself is returning false in some cases...for
> instance:
>
> $irb
> >> v1 = 80.04
> => 80.04
>
> >> v2 = 0.12 * 667
> => 80.04
>
> >> v1 == v2
> => false
>
> >> v1 > v2
> => true
>
> >> v1 < v2
> => false
>
> >> v1.inspect
> => "80.04"
>
> >> v2.inspect
> => "80.04"
>
> Any insight?
>

Machine roundoff error. Floating point values are never precise on any
computer.

Hmm...yeah, I figured that must be it, but I just didn't expect it with
numbers of this scale. Thanks for the insight!

Thom

···

--
Posted via http://www.ruby-forum.com/.

boy, how bout an rcr for that behaviour if one write this

   2.0 =~ 2.0

??

-a

···

On Thu, 9 Nov 2006, Tim Pease wrote:

Machine roundoff error. Floating point values are never precise on any computer.

The best way to compare two floating point values is to take there
difference and make sure it lies withing some acceptable error limit.

v1 = 80.04
v2 = 0.12 * 667
diff = v1-v2
diff.abs < Float::EPSILON

That last line returns false, so you need to choose a different epsilon ...

diff.abs < 1.0e-12

That will return true.

--
my religion is very simple. my religion is kindness. -- the dalai lama

* Thom Loring, 11/08/2006 06:35 PM:
> Any insight?

Visit an introduction to Numerical Mathematics at your favorite
university.

That would of course be great, but one ends up with diving in a a lot deeper
than necessary, which is too a whole lot of fun, but not always practical
when one has a set objective.

:slight_smile:

Wouldn't a good book(s) be a better, perhaps you could suggest some :slight_smile:

Regards,

- vihan

Jupp:

Visit an introduction to Numerical Mathematics at your favorite
university. Numerical imprecision and the stability of algorithms
against it is one of the most prominent questions addressed there.
Also they address the question how precise a result of a computation
can be given a certain imprecision of input that either results from
the computer's approximation to a given value (decimal 0.1 cannot be
represented as a binary fraction with a finite number of digits) or
from imprecisely known values - which includes any measured quantity
occuring in natural science (actually all quantities that are not
defined by law as it is the case with vacuum light speed that by law
is defined to be precisely 299792458 m/s).

It's jolly decent of light to be so obliging about the speed it travels
at. I count myself very lucky to live in a universe where it takes on an
integer speed.

:wink:

With IEEE 754 floating point values you only have 15 digits of
precision (8 byte doubles). Ara's little example above demonstrates
that very nicely. Things go pear shaped in the 17th digit with the
"exact" value 80.04 (v1).

Take a look at the "assert_in_delta" method of the Test::Unit library.
That performs floating point comparison by comparing a diff against
some epsilon (delta).

<shameless plug>
There is an RCR open to implement a =~ operator for floating point
values that would perform a diff comparison against an epsilon value.

http://rcrchive.net/rcr/show/340
</shameless plug>

Blessings,
TwP

···

On 11/8/06, Hugh Sasse <hgs@dmu.ac.uk> wrote:

>
> Machine roundoff error. Floating point values are never precise on any
> computer.
>
brains hgs 226 %> irb
irb(main):001:0> v1 = 80.04
=> 80.04
irb(main):002:0> v2 = 0.12 * 667
=> 80.04
irb(main):003:0> puts "%.20f" % v1
80.04000000000000625278
=> nil
irb(main):004:0> puts "%.20f" % v2
80.03999999999999204192
=> nil
irb(main):005:0> exit
brains hgs 227 %>

Thom Loring wrote:

Hmm...yeah, I figured that must be it, but I just didn't expect it with
numbers of this scale. Thanks for the insight!

It isn't about the magnitude of the numbers, it is about the unseen bits.

You could produce examples of numbers with very large or very small
exponents and they are equally likely to have the sort of roundoff error
you experienced.

The only thing you can rely on with floating-point numbers is that the same
sequence of operations, on the same platform, will produce numbers that
will agree with each other when compared later.

There are many packages now that use decimal instead of binary internal
storage to avoid this sort of thing, at the expense of execution speed and
storage space. But an interesting fact about binary vs. decimal is that
projects that compute Pi to billions of places, now perform the entire
operation in decimal internally, because the time required to convert the
result from binary to decimal at the end of the computation turned out to
be a substantial percentage of the entire calculation time.

···

--
Paul Lutus
http://www.arachnoid.com

It's jolly decent of light to be so obliging about the speed it travels
at. I count myself very lucky to live in a universe where it takes on an
integer speed.

:wink:

True, but thats in m/s, if you like other units its not so jolly :slight_smile:

1,079,252,848.8 km/h
186,282.397 mi/sec
670,616,629.384 mi/hr

:slight_smile:

Regards,

- vihan

<errata>
Sorry, that should be "Hugh's little example above".
</errata>

TwP

···

On 11/8/06, Tim Pease <tim.pease@gmail.com> wrote:

On 11/8/06, Hugh Sasse <hgs@dmu.ac.uk> wrote:

With IEEE 754 floating point values you only have 15 digits of
precision (8 byte doubles). Ara's little example above demonstrates
that very nicely. Things go pear shaped in the 17th digit with the
"exact" value 80.04 (v1).

> irb(main):002:0> v2 = 0.12 * 667
> => 80.04

        [...]

> irb(main):004:0> puts "%.20f" % v2
> 80.03999999999999204192

        [...]

With IEEE 754 floating point values you only have 15 digits of

I just picked a large value. This seemed the clearest way to show
what was going on, from my viewpoint.

precision (8 byte doubles). Ara's little example above demonstrates
that very nicely. Things go pear shaped in the 17th digit with the
"exact" value 80.04 (v1).

[other good points trimmed]
        Hugh

···

On Thu, 9 Nov 2006, Tim Pease wrote:

On 11/8/06, Hugh Sasse <hgs@dmu.ac.uk> wrote: