Floating point resolution at a given number - c++

I would like to know the epsilon of a floating point number around a given value.
std::numeric_limits<floating_point_type>::epsilon() provides that only for the number 1.0, while I would like a function to work on any number.
Is there any standard library solution to this? If not - how should I implement the function?

Well, the easiest solution to find the epsilon immediately above the value (that is, the distance from that value to the next representable value) would just be
std::nextafter(x, std::numeric_limits<floating_point_type>::infinity()) - x
Similarly to find the epsilon below the value, you could do
x - std::nextafter(x, -std::numeric_limits<floating_point_type>::infinity())
Note that those two won't be the same if x is an exact power of two.
Now, there is one slight caveat there: the calculated epsilon above FLT_MAX will be infinity (arguably that's kind of the correct answer, but it doesn't quite match IEEE-754's rounding rules) and the epsilon above infinity will be NaN (which, well, I don't know how I feel about that). In all other cases, the result will be exact.

Related

Is there an easy way in C++ to round to the nearest 1.75 increment

I tried looking up this on StackOverflow, close this question if this has been answered already. But is there a function in C++ that can round a value to an increment with a decimal value? Please generalize your answer for any given decimal increment - I would like to also know, for example, how to round to the nearest 1.78 increment.
There is no specific function to do that, but you can easily make one. Just divide the value by 1.75, then call std::round and then multiply by 1.75.
e.g.
double round_to_multiple(double val, double step)
{
return step * std::round(val / step);
}
Where "step" is the step-size, or multiple. In your case, 1.75.
Just be wary of floating-point rounding error. If you are always dealing with 2 decimal places and the numbers you work with are in a useful range, you might want to consider using integers instead (multiplied by 100), which would change the technique a little.

how could minimal value of float number smaller than precision? [duplicate]

I was solving an equation using double precision and I got -7.07649e-17 as a solution instead of 0.
I agree it's close enough that I can say it's equal but I've read that the machine epsilon for the C++ double type is 2^-52 which is larger than the value I get.
So why do I have an inferior value than the machine epsilon?
Why isn't the value rounded to zero?
It's not a big deal but when I do a logical test it appears that my value is not zero...
There are two different constants in this story. One is epsilon, which is a minimal value that when added to 1.0 produces a value different from 1.0. If you add a smaller value to 1.0 you will again get a 1.0, because there are physical limits to the representation of a number in a computer. But there are values that are less than epsilon and greater than zero. Smallest such number for a double you get with std::numeric_limits<double>::min.
For reference, you get epsilon with std::numeric_limits<double>::epsilon.
You are not guaranteed that rounding will take place at any particular time. The C++ standard permits the implementation to use additional precision pretty much anywhere it wants to and many real-world implementations do exactly that.
A common solution for the floating point precision problem is to define an epsilon value yourself and compare to that instead of zero.
e.g.
double epsilon = 0.00001;
if (abs(value) < epsilon) // treat value as 0 in your code

Why my double can contain a value below the machine epsilon?

I was solving an equation using double precision and I got -7.07649e-17 as a solution instead of 0.
I agree it's close enough that I can say it's equal but I've read that the machine epsilon for the C++ double type is 2^-52 which is larger than the value I get.
So why do I have an inferior value than the machine epsilon?
Why isn't the value rounded to zero?
It's not a big deal but when I do a logical test it appears that my value is not zero...
There are two different constants in this story. One is epsilon, which is a minimal value that when added to 1.0 produces a value different from 1.0. If you add a smaller value to 1.0 you will again get a 1.0, because there are physical limits to the representation of a number in a computer. But there are values that are less than epsilon and greater than zero. Smallest such number for a double you get with std::numeric_limits<double>::min.
For reference, you get epsilon with std::numeric_limits<double>::epsilon.
You are not guaranteed that rounding will take place at any particular time. The C++ standard permits the implementation to use additional precision pretty much anywhere it wants to and many real-world implementations do exactly that.
A common solution for the floating point precision problem is to define an epsilon value yourself and compare to that instead of zero.
e.g.
double epsilon = 0.00001;
if (abs(value) < epsilon) // treat value as 0 in your code

How do I check and handle numbers very close to zero

I have some math (in C++) which seems to be generating some very small, near zero, numbers (I suspect the trig function calls are my real problem), but I'd like to detect these cases so that I can study them in more detail.
I'm currently trying out the following, is it correct?
if ( std::abs(x) < DBL_MIN ) {
log_debug("detected small num, %Le, %Le", x, y);
}
Second, the nature of the mathematics is trigonometric in nature (aka using a lot of radian/degree conversions and sin/cos/tan calls, etc), what sort of transformations can I do to avoid mathematical errors?
Obviously for multiplications I can use a log transform - what else?
Contrary to widespread belief, DBL_MIN is not the smallest positive double value but the smallest positive normalized double value. Typically - for 64-bit ieee754 doubles - it's 2-1022, while the smallest positive double value is 2-1074. Therefore
I'm currently trying out the following, is it correct?
if ( std::abs(x) < DBL_MIN ) {
log_debug("detected small num, %Le, %Le", x, y);
}
may have an affirmative answer. The condition checks whether x is a denormalized (also called subnormal) number or ±0.0. Without knowing more about your specific situation, I cannot tell if that test is appropriate. Denormalized numbers can be legitimate results of calculations or the consequence of rounding where the correct result would be 0. It is also possible that rounding produces numbers of far greater magnitude than DBL_MIN when the mathematically correct result would be 0, so a much larger threshold could be sensible.
If x is a double, then one problem with this approach is that you can't distinguish between x being legitimately zero, and x being a positive value smaller than DBL_MIN. So this will work if you know x can never be legitimately zero, and you want to see when underflow occurs.
You could also try catching the SIGFPE signal, which will fire on a POSIX-compliant system any time there's a math error including floating-point underflow. See: http://en.wikipedia.org/wiki/SIGFPE
EDIT: To be clear, DBL_MIN is NOT the largest negative value that a double can hold, it is the smallest positive normalized value that a double can hold. So your approach is fine as long as the value can't be zero.
Another useful constant is DBL_EPSILON which is the smallest double value that can be added to 1.0 without getting 1.0 back. Note that this is a much larger value than DBL_MIN. But it may be useful to you since you're doing trigonometric functions that may tend toward 1 instead of tending toward 0.
Since you are using C++, the most idiomatic is to use std::numeric_limits from header <limits>.
For instance:
template <typename T>
bool is_close_to_zero(T x)
{
return std::abs(x) < std::numeric_limits<T>::epsilon();
}
The actual tolerance to be used heavily depends on your problem. Please complete your question with a concrete use case so that I can enhance my answer.
There is also std::numeric_limits<T>::min() and std::numeric_limits<T>::denorm_min() that may be useful. The first one is the smallest positive non-denormalized value of type T (equal to FLT/DBL/LDBL_MIN from <cfloat>), the second one is the smallest positive value of type T (no <cfloat> equivalent).
[You may find this document useful to read if you aren't at ease with floating point numbers representation.]
The first if check will actually only be true when your value is zero.
For your second question, you imply lots of conversions. Instead, pick one unit (deg or rad) and do all your computational operations in that unit. Then at the very end do a single conversion to the other value if you need to.

Comparing doubles to double literals? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How should I do floating point comparison?
Is it not recommended to compare for equality a double and a double literal in C++, because I guess it is compiler dependent?
To be more precise it is not OK to compare a double which is hard-coded (a literal in the source code) and a double which should be computed, as the last number of the resultant of the calculation can vary from one compiler to another. Is this not standardized?
I heard this is mentioned in Knuth's TeXbook, is that right?
If this is all true, what is the solution?
You've misunderstood the advice a bit. The point is that floating-point computations aren't exact. Rounding errors occur, and precision is gradually lost. Take something as simple as 1.0/10.0. The result should be 0.1, but it isn't, because 0.1 cannot be represented exactly in floating-point format. So the actual result will be slightly different. The same is true for countless other operations, so the point has nothing to do with const doubles. It has to do with not expecting the result to be exact. If you perform some computation where the result should be 1.0, then you should not test it for equality against 1.0, because rounding errors might mean that it actually came out 0.9999999997 instead.
So the usual solution is to test if the result is sufficiently close to 1.0. If it is close, then we assume "it's good enough", and act as if the result had been 1.0.
The bottom line is that strict equality is rarely used for floating-point values. Instead, you should test if the difference between the two values is less than some small value (typically called the epsilon)
The problem you are talking about is due to rounding errors and will happen for every floating point number. What you can do is define an epsilon and see if the difference between the two floating point numbers is smaller than this. E.g.:
double A = somethingA();
double B = somethingB();
double epsilon = 0.00001;
if (abs(A - B) < epsilon)
doublesAreEqual();
[Edit] Also see this question: What is the most effective way for float and double comparison?.
The key problem is how floating point arithmetic works - it includes rounding that can lead to comparison for equality evaluated wrong. This applies to all floating point numbers regardless of whether variable is declared const or not.
if you do floating point calculations and you need to do comparisons with certain fixed values it is always safer to use an epsilon value to take into account precision errors .
Example:
double calcSomeStuf();
if ( calcSomeStuf() == 0.1 ) { ...}
is a bad idea
however:
const double epsilon = 0.005
double calcSomeStuf();
if ( abs(calcSomeStuf() - 0.1) < epsilon ) { ...}
is a lot safer (especially considering the fact that 0.1 cannot be represented exactly as a double)
This is necessary because when accumulating floating point operations rounding errors occur, and due to the nature of floating point not all numbers can be represented exactly