views:

213

answers:

4

Due to the difficulty for machine to represent floating point values exactly, we are using the a technique from Write Great Code: Understanding the machine to perform floating point comparisons:

from the editor: please insert your code here. See HTML comment in the question source

Currently, we hard coded the 'error' value. But the error is different across different machine. Is there any good way to figure out, the error for a particular machine, instead of hard-coding a tolerance?

+4  A: 

See my answer to What’s the smallest non-zero, positive floating-point number in Perl?.

That code finds the smallest positive number that cannot be distinguished from zero. You can adapt it to your needs.

Sinan Ünür
Is it possible that we can go into infinity loop in edge case? Although it seems not at first glance.
Yan Cheng CHEOK
And that seems to be "approximate", not "exactly".
Yan Cheng CHEOK
@Yan Cheng Cheok I am no numerical analyst and I do not know all the intricacies of floating point math in all its varieties, but I do not think so because floating point numbers can only represent a finite number of values. If you are working with decimal floating point (unlikely, but possible), then you should divide by 10.
Sinan Ünür
@Yan Cheng Cheok it will be exact if you are working with binary floating point.
Sinan Ünür
Even if they make a super-duper-infinitely-precise CPU in the future, you can avoid infinite loops by counting the iterations and breaking after a while (I suppose 60-70 iterations would be enough).
DrJokepu
@DrJokepu agreed. But let's make it an even 100 while we are at it ;-)
Sinan Ünür
+1  A: 

The "machine precision" that determines the accuracy of a double or float is typically labeled epsilon.

If I need to calculate the precision of a floating point number, I will typically do something like this*:

float number = 1.0;      // precision of this number
float epsilon = 1.0;

while ((number + epsilon) != number)
{
    epsilon /= 2.0f;
}

(*This is off the top of my head. Don't use this code without checking.)

But there are ways to determine the exact precision given the properties of the machine.

Here is an article about How to determine the machine epsilon with code examples.

And another one here: Floating Point: Machine Precision with the theory and equations to calculate epsilon.

Enjoy,

Robert C. Cartaino

Robert Cartaino
+3  A: 

For 64-bit IEEE 754 floating point, the smallest number such that 1.0 + e != 1.0 is e = 2.2204460492503131e-016. (DBL_EPSILON in float.h in C, std::numeric_limits<double>().epsilon() in <limits> in C++). I think it's unlikely that your code will be running on any systems where the native floating-point format is not 64-bit IEEE 754.

Note that the absolute precision actually changes depending on what magnitude of numbers you're dealing with. With denormals, you operate on extremely small values, so 1e-300 + 2e-300 will work, but 1 + 1e-300 == 1. Similarly 1e30 + 1 == 1e30.

Tim Sylvester
+3  A: 

I usually determine what precision i want in my system, without worrying too much about the precision available to me. This works correctly in most cases I ran across with. Some of the advantages I can think of of this approach is that

  • It lets me focus on the problem I am trying to solve faster.
  • I dont have to spend time trying to figure out the epsilon!
  • also, and this is an important point: the epsilon changes depending on where you are on the number system. The epsilon is different near 0, and different near, say 2 ^ 300. So to actually plug in an epsilon, you also need to know which number range you are trying to figure out epsilon for. I suggest using Sinan Unur's answer, but do the calculation near the boundary values of the number range you are likely to run into, and then using an epsilon which is slightly larger than the maximum value.
  • verify point three, its just a hunch!
Yes, the epsilon does depend on the number under consideration. For `1_000_000`, it is `1.1641532182693481e-010` and for `1_000_000_000`, it is `1.1920928955078125e-007`.
Sinan Ünür