Simple question on floating-point errors
Author Message
Simple question on floating-point errors

When you perform arithmetic operations on numbers of type float, small
errors creep in to the calculation. I have found that tests of strict
equality frequently fail, e.g. I am told that 0.10000 is not in fact
equal to 0.10000. This is not something I have come across in other
languages. My question is: what is the quick and ready solution to the
problem? Some type conversion? Any help would be much appreciated.

Thanks,

--
Je suis avec les sentiments de respect et de reconnaissance qu'on doit
aux hommes misericordieux et bienfaisants, monsieur, votre tres-humble
et tres-obeissante servante,
Signe: James McCabe

Sat, 17 Feb 1996 01:23:52 GMT
Simple question on floating-point errors

Quote:
>When you perform arithmetic operations on numbers of type float, small
>errors creep in to the calculation. I have found that tests of strict
>equality frequently fail, e.g. I am told that 0.10000 is not in fact
>equal to 0.10000. This is not something I have come across in other
>languages. My question is: what is the quick and ready solution to the
>problem? Some type conversion? Any help would be much appreciated.

If you haven't run across it in other languages, then either you're
finally doing real (pardon the pun) things in C and you haven't done
them in other languages, or those languages don't use the native
floating-point repreentation (native for the machines they were on).

1/10 is not representable in base 2, any more than 1/3 is representable
in decimal - and for the same reasons.  Any language that guarantees
that the equivalent of this loop terminates:

inc = 0.00001
loop = 0
while ( loop != 1.0 )
loop = loop + inc

is performing special floating-point voodoo.  I'm not aware of any language
where this wil terminate.

--
#include        <standard.disclaimer>
_
Kevin D Quitt                   96.37% of all statistics are made up

Sat, 17 Feb 1996 02:35:34 GMT
Simple question on floating-point errors

Quote:
> When you perform arithmetic operations on numbers of type float, small
> errors creep in to the calculation. I have found that tests of strict
> equality frequently fail, e.g. I am told that 0.10000 is not in fact
> equal to 0.10000. This is not something I have come across in other
> languages. My question is: what is the quick and ready solution to the
> problem? Some type conversion? Any help would be much appreciated.

Either use a language that supports BCD (Binary Coded Decimal) or find
something in C to do it. I wouldn't mind getting something like this myself
if it is portable and easily understandable to someone who understands
mathematics and C programming. The number you refer to is a repeating
decimal in Base-2 (binary) and is 0.000011 with the digits after the
decimal repeating. So something like this for the computer is just as hard
as the number would be in Base-10 without using fractions ;)
--
Jonas Schlein

Sat, 17 Feb 1996 07:05:43 GMT
Simple question on floating-point errors

Quote:
>When you perform arithmetic operations on numbers of type float, small
>errors creep in to the calculation. I have found that tests of strict
>equality frequently fail, e.g. I am told that 0.10000 is not in fact
>equal to 0.10000. This is not something I have come across in other
>languages. My question is: what is the quick and ready solution to the
>problem? Some type conversion? Any help would be much appreciated.

In general, floating point numbers should always be regarded as
_approximations_ to real numbers.  Most machines now perform exact
calculations on some numbers (e.g. adds and multiplies of floats with
small integer values), but even this has not always been the case.
Divisions of floats should always be regarded with caution, even when the
operands and the result could, in principle, be represented exactly.

Quantities of type "int" on the other hand, are exact representations of
integers.  In most languages, operations involving integers are well-
defined.  This is true in C, except for results involving divisions of
negative integers.  C allows some ambiguity for such results, and this is
the root of recurring flame wars, ahem, discussions in this and other
language newsgroups.

The solution to your problem depends on exactly what your problem is.  If
it is that (1./10. == 0.1) fails, then there is not much that can be
done.  This simply reflects that a real number cannot be represented
exactly as a float, and different ways of computing this number end up
having different approximations.  On the other hand, if you can transform
this to an integer comparison like (10 == 2*5), and this usually involves
more than simple type conversion, then things will work correctly.

\$.02 -Ron Shepard

Sat, 17 Feb 1996 07:18:00 GMT
Simple question on floating-point errors

Quote:

>> When you perform arithmetic operations on numbers of type float, small
>> errors creep in to the calculation. I have found that tests of strict
>> equality frequently fail, e.g. I am told that 0.10000 is not in fact
>> equal to 0.10000. This is not something I have come across in other
>> languages. My question is: what is the quick and ready solution to the
>> problem? Some type conversion? Any help would be much appreciated.
>Either use a language that supports BCD (Binary Coded Decimal)

That won't work either. Consider division by three ...that can't be
represented exactly in BCD either.

There is no solution except to test for "near equality". (unless,
of course you are doing certain financial calculations in which
using integer pennies may  (or may not) work.

Doug McDonald

Sat, 17 Feb 1996 08:00:34 GMT
Simple question on floating-point errors

Quote:
> When you perform arithmetic operations on numbers of type float, small
> errors creep in to the calculation. I have found that tests of strict
> equality frequently fail, e.g. I am told that 0.10000 is not in fact
> equal to 0.10000. This is not something I have come across in other
> languages. My question is: what is the quick and ready solution to the
> problem? Some type conversion? Any help would be much appreciated.

This question comes up periodically, and almost invariably prompts the
same series of responses, some of which, alas, are misleading.
Because FP representations do not include all real (or rational)
numbers, it is true that a given FP quantity is usually intended to be
an approximation to some ideal real quantity.  However, respondants to
this approximation.  For architectures of any wide-spread importance
these days, FP arithmetic is deterministic [Note 1], and for many of
those---notably IEEE-compliant FP (as on IBM PCs, e.g.)---rather well-
behaved.  As long as you know what arithmetic engine your software is
intended for (or you are willing to support multiple versions), it
seems to me that you may as well count on a particular behavior, if it
yields significant advantages in performance (or whatever) to do so.

For example, in IEEE arithmetic, if the quotient of two integers is a
representable IEEE number (in some format), and if those integers are
themselves representable in that format, then the quotient will be
exact.  As another example, if two positive IEEE FP numbers are within
a factor of two of each other, their difference will be exact.
your application.  If you are using a particular FP value as an input
sentinel (to mark the end of some input data) and it is a
representable quantity, then naive use of the equality test should
work.  Likewise, if you have a formula such as

something / (x - 1.5)

then (under IEEE arithmetic) the code

if (x == 1.5)
return /* the value at singular point x==1.5 */;
else
return something / (x - 1.5)

will not divide by 0 (although come to think of it, there are ways a poor
compiler could{*filter*}this up).

Others have posted locutions that sometimes work in other cases, but
none works universally.  In particular, the routine translation of
"real" equality into some "fuzzy" equality, such as

x = y  ---->    abs(x-y) < EPSILON * abs(x)

is not a great idea.

NOTES:

1. On some architectures (some Honeywell models spring to mind) FP
arithmetic is actually non-deterministic as implemented by their
compilers and OS.  The FP registers contain bits that are not included
when a quantity is stored to memory, as happens in response to context
switch resulting from an interrupt.  As a result, the value of a
subexpression or temporary may change in the last significant bits
unpredictably.  I can count the number of times I've used such
architectures on the fingers of one elbow.

P. Hilfinger

Sat, 17 Feb 1996 10:06:11 GMT
Simple question on floating-point errors

Quote:
> When you perform arithmetic operations on numbers of type float, small
> errors creep in to the calculation. I have found that tests of strict
> equality frequently fail, e.g. I am told that 0.10000 is not in fact
> equal to 0.10000. This is not something I have come across in other
> languages. My question is: what is the quick and ready solution to the
> problem? Some type conversion? Any help would be much appreciated.

> Thanks,

> --
>   Je suis avec les sentiments de respect et de reconnaissance qu'on doit
> aux hommes misericordieux et bienfaisants, monsieur, votre tres-humble
> et tres-obeissante servante,
>                                    Signe: James McCabe

Where this is a problem, for instance dealing with money, I don't
use floats.  I do dollars and cents in cents and use longs.  The longs
represents pennys.  When it is necessary to display a dollar amount, just
insert a decimal point two spots from the right.

ken

Sun, 18 Feb 1996 23:27:08 GMT
Simple question on floating-point errors
Using floating point is a little like moving a pile of sand. Each time
you move it, you lose a little, and a little dirt gets mixed in.

There is no "answer" to your question as posed. It depends on what you
are trying to do with the floating point. It is not *supposed* to be the
case that 0.1 is not equal to 0.1, but it has been *known* to happen.
This occurs when the conversion routines used in the compiler do not
produce the same results as those used in the run-time-library for
(e.g.) sscanf.

Using BCD may be the way to go. But almost certainly not for intensive
calculations, and also almost certainly not for scientific calculations.
Another "solution" is to use rational arithmetic.

Still another is to use "almost equal" comparisons. E.G.

if (fabs(x-y) < epsilon) {
/* case where they are considered equal */
} else {
/* case where they are considered unequal */
}

I once had a problem in fortran when I was working on a statistical
program which did a lot of hypothesis testing. Needed to not divide by
zero in some places. The code looked something like this:

if x .ne. y goto 100
result = undefined
goto 200
100     continue
result = z/(x-y)
200     continue
...

It was dividing by zero. It turned out that x and y were unequal, but
x-y was still 0. You might want to get an introductory text on Numerical
Analysis at your local college bookstore.

Mike

Sun, 18 Feb 1996 23:41:25 GMT

 Page 1 of 1 [ 8 post ]

Relevant Pages