The floating point comparison is exact, so 10^-10 is not the same as 0.0.
Basically, you should be comparing against some tolerable difference, say 10^-7 based on the number of decimals you're writing out, that can be accomplished as:
while(fabs(tmp) > 10e-7)
Answer from Mark Elliot on Stack OverflowThe floating point comparison is exact, so 10^-10 is not the same as 0.0.
Basically, you should be comparing against some tolerable difference, say 10^-7 based on the number of decimals you're writing out, that can be accomplished as:
while(fabs(tmp) > 10e-7)
Don't use exact equality operations when dealing with floating point numbers. Although your number may look like 0, it likely to be something like 0.00000000000000000000001.
You'll see this if you use %.50f instead of %f in your format strings. The latter uses a sensible default for decimal places (6 in your case) but the former explicitly states you want a lot.
For safety, use a delta to check if it's close enough, such as:
if (fabs (val) < 0.0001) {
// close enough.
}
Obviously, the delta depends entirely on your needs. If you're talking money, 10-5 may be plenty. If you're a physicist, you should probably choose a smaller value.
Of course, if you're a mathematician, no inaccuracy is small enough :-)
You are correct with your observation.
If x == 0.0, then abs(x) * epsilon is zero and you're testing whether abs(y) <= 0.0.
If y == 0.0 then you're testing abs(x) <= abs(x) * epsilon which means either epsilon >= 1 (it isn't) or x == 0.0.
So either is_equal(val, 0.0) or is_equal(0.0, val) would be pointless, and you could just say val == 0.0. If you want to only accept exactly +0.0 and -0.0.
The FAQ's recommendation in this case is of limited utility. There is no "one size fits all" floating-point comparison. You have to think about the semantics of your variables, the acceptable range of values, and the magnitude of error introduced by your computations. Even the FAQ mentions a caveat, saying this function is not usually a problem "when the magnitudes of x and y are significantly larger than epsilon, but your mileage may vary".
If you are only interested in +0.0 and -0.0, you can use fpclassify from <cmath>. For instance:
if( FP_ZERO == fpclassify(x) ) do_something;
How to check for equality against absolu - C++ Forum
c++ - float/double equality with exact zero - Stack Overflow
Hot to correctly compare two double values?
c - Checking for when a double is a Zero - Stack Overflow
It depends on how b and a got their values. Zero has an exact representation in floating point format, but the bigger problem would be almost-but-not-quite zero values. It would always be safe to check:
if (abs(b-a) > 0.00000001 && ...
Where 0.00000001 is whatever value makes sense.
Here's how you do it: instead of checking for (result < small_number), you check for
(abs(c) < abs(b - a) * small_number)
Then all your troubles disappear! The computation of c/(b-a) will never overflow if this test is passed.
I'm working on a school project, where I user defines points of a triangle. I then need to calculate, if those points aren't on the same line, so it's possible to form a triangle. Im using something like this:
`double value=(ba1 * (bb2-bc2) + bb1 * (bc2-ba2) + bc1 * (ba2-bb2));`
if (fabs(value)==0){
printf("It's a not triangle\n");
}
`else{`printf("It's a triangle\n");
}
But even when I should get the message that it's not a triangle, I don't. How to get over that?
You can use the standard macro signbit(arg) from math.h. It will return nonzero value if arg is negative and 0 otherwise.
From the man page:
signbit()is a generic macro which can work on all real floating- point types. It returns a nonzero value if the value of x has its sign bit set.This is not the same as x < 0.0, because IEEE 754 floating point allows zero to be signed. The comparison -0.0 < 0.0 is false, but signbit(-0.0) will return a nonzero value.
NaNs and infinities have a sign bit.
Also, from cppreference.com:
This macro detects the sign bit of zeroes, infinities, and NaNs. Along with
copysign, this macro is one of the only two portable ways to examine the sign of a NaN.
Very few calculations actually give you a signed negative zero. What you're probably observing is a negative value close to zero that has been truncated by your formatting choice when outputting the value.
Note that -0.0 is defined to be equal to 0.0, so a simple comparison to 0.0 is enough to verify a signed zero.
If you want to convert an exact signed zero -0.0 to 0.0 then add 0.0 to it.
Is it OK to compare doubles in C? Like a == b. Will it give me correct results everytime? If not, workarounds?
What happens when doubles overflow? Does the C state machine go into an undefined state and then your program behavior is undefined/non deterministic? Or does something else happen? How does one prevent this from happening?
The value ±0 only indicates if the value approached 0 from negative or positive values (but this is not a guarantee for every case, of course). However, it still is 0.
Therefore, x >= 0 will include both +0 and -0 zero. You can test that for yourself in a simple program. :)
In the IEEE754 standard, it explicitly says
Comparisons shall ignore the sign of zero (so +0 = -0).
IEEE754 is used by most processors and implementations, so for all practical purposes -0 >= 0 is true.
For any number x, x >= 0 and !(x < 0) are the same. This is also true for +0 and -0.
As pointed out by aschepler in a comment, the two tests x >= 0 and !(x < 0) differ when x is NaN (not-a-number). NaN is always different from any real number, thus !(x < 0) will be true when x is NaN.
If NaN can occur in your calculations, you may want to handle that separately.
Yes you can test both
if(myDoubleValue >= 0.0)
and
if(!(myDoubleValue < 0.0))
You can use strtod. Check if the result is zero and subsequently if endptr == nptr, according to the man page:
If no conversion is performed, zero is returned and the value of nptr is stored in the location referenced by endptr.
Something like this:
char input[50];
char * end;
double result = 0;
fgets(input, sizeof input, stdin);
errno = 0;
result = strtod(input, &end);
if(result == 0 && (errno != 0 || end == input)){
fprintf(stderr, "Error: input is not a valid double\n");
exit(EXIT_FAILURE);
}
EDIT there seems to be a bit of a discrepancy between the standard and the man page. The man page says that endptr == nptr when no conversion is performed, while the standard seems to imply this isn't necessarily the case. Worse still it says that in case of no conversion errno may be set to EINVAL. Edited the example code to check errno as well.
Alternatively, sscanf could be used (preferred over scanf), in conjunction with fgets:
/* just fgetsed input */
if(sscanf(input, "%lf", &result) != 1){
fprintf(stderr, "Error: input is not a valid double\n");
exit(EXIT_FAILURE);
}
Also, don't forget to check the return value of fgets for NULL, in case it failed!
Neither simple strtod nor sscanf are enough to distinguish cases such as 1,5 or 1blah from desired 1.0 - All of these will result in 1.0. The reason is that
The
strtod(),strtof(), andstrtold()functions convert the initial portion of the string pointed to by nptr to double, float, and long double representation, respectively.
To ensure that the entire string was a valid double literal, use strtod like this:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
...
char *endptr;
errno = 0;
double result = strtod(input, &endptr);
if (errno != 0 || *endptr != '\0') {
fprintf(stderr, "the value could not be represented as a double exactly\n");
}
The errno will be set if the value cannot be represented (ERANGE). Additionally, end will be pointing to the first character not converted. If the locale has not been set, when parsing 1,5 or 1blah, endptr will point to the second character. Iff the entire string was successfully parsed as a double constant, *endptr will point to the terminating '\0'.
Note that the errno must be set to zero prior to calling the function, otherwise it will retain the value from a previous failed function call.
Assuming 64-bit IEEE double, there is a 52-bit mantissa and 11-bit exponent. Let's break it to bits:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^0 = 1
The smallest representable number greater than 1:
1.0000 00000000 00000000 00000000 00000000 00000000 00000001 × 2^0 = 1 + 2^-52
Therefore:
epsilon = (1 + 2^-52) - 1 = 2^-52
Are there any numbers between 0 and epsilon? Plenty... E.g. the minimal positive representable (normal) number is:
1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^-1022 = 2^-1022
In fact there are (1022 - 52 + 1)×2^52 = 4372995238176751616 numbers between 0 and epsilon, which is 47% of all the positive representable numbers...
The test certainly is not the same as someValue == 0. The whole idea of floating-point numbers is that they store an exponent and a significand. They therefore represent a value with a certain number of binary significant figures of precision (53 in the case of an IEEE double). The representable values are much more densely packed near 0 than they are near 1.
To use a more familiar decimal system, suppose you store a decimal value "to 4 significant figures" with exponent. Then the next representable value greater than 1 is 1.001 * 10^0, and epsilon is 1.000 * 10^-3. But 1.000 * 10^-4 is also representable, assuming that the exponent can store -4. You can take my word for it that an IEEE double can store exponents less than the exponent of epsilon.
You can't tell from this code alone whether it makes sense or not to use epsilon specifically as the bound, you need to look at the context. It may be that epsilon is a reasonable estimate of the error in the calculation that produced someValue, and it may be that it isn't.
Before dabbling with graphics I was unaware that there can be issues with comparing floating point numbers and that leads me to ask these questions here:
-
Should
==and!=always be avoided when comparing floating point numbers or not and if so should one instead compare using anepsilonor something else? -
Are there any issues I need to know about when wanting to sort out unique floating point values either by:
-
using something in
<algorithm>in a container or by -
using containers such as ordered and unordered
sets/mapswhen wanting to use them as a unique key?
Thanks