# Thread: Most Efficient Way to Check a Variable Is A Whole Number

1. Originally Posted by iMalc
Less likely to be a problem of course, but a double still far exceeds the range of a long long. So 2^100 (which is exactly representable in a double) isn't a whole number with that approach.
But then you probably already knew that.
I forgot to add that this will actually work if you check the double for being outside the range of about say -2^60 to 2^60 first, returning true in that case, because a double doesn't have enough significand bits to represent such large numbers with any decimal places at all.

2. Originally Posted by Daved
What about my example? It gives incorrect output.
As a matter of fact, it gives correct output. Your code correctly detected that a floating point variable with the value (approximately) 42.993 does not contain an integral value.

Your error was in expecting that the series of calculations that produced the value would yield an integral value.

3. You're telling me that (1000.43 - 1000.00)*100 is not a whole number?

I'm sure you can understand the point that I was making. If you'd like to address that feel free, but your comments don't make sense in the context of my original advice, which I still think is important for the OP to understand.

4. You could do it like:

Code:
```if (!(a_dbl - (int)a_dbl))
{
}```

5. See iMalc's first post to see why that might not work.

6. There's also modf. It breaks a floating-point number into an integral and a fractional part. I'm not sure how efficient it is, but it's perfect for this situation.

Sorry for the C example code; I didn't notice what forum I was in.  See the C++ code below. [/edit]
Code:
```#include <stdio.h>
#include <math.h>

void check(double x) {
double fractional, integral;
fractional = modf(x, &fractional);
printf(fractional == 0.0 ? "an integer" : "not an integer");
}

int main() {
printf("3.0 is ");
check(3.0);
putchar('\n');

printf("3.5 is ");
check(3.5);
putchar('\n');

return 0;
}```
 In C++:
Code:
```#include <cmath>

bool is_integer(double number) {
double fractional;  // ignored
return modf(number, &fractional) == 0.0;
}```
I used the dummy variable fractional since modf doesn't support passing NULL for the integral part parameter.

I know I'm comparing floating point numbers with == here, but since I'm comparing with 0.0 it should be okay in most cases.
[/edit]

7. dwks, the second parameter should be the buffer for the integral part (typo, I'm assuming?).

8. Umm, not as far as I know? The "buffer" here is of type double, as I've supplied. Seriously, try my C++ function. It should work.

Where exactly is the suspect phrase in my post?

What I was trying to say is that modf doesn't let you supply NULL for the second parameter if you don't want to get the integral part of it. You have to supply a double pointer for it to overwrite.

9. Oh, ok, well it's just a little misleading then (ie: perhaps using "integral" or similar (or even "unused" as the variable name might be more appropriate then "fractional"). At any rate, the code works correctly.

10. Originally Posted by Daved
You're telling me that (1000.43 - 1000.00)*100 is not a whole number?

I'm sure you can understand the point that I was making. If you'd like to address that feel free, but your comments don't make sense in the context of my original advice, which I still think is important for the OP to understand.
I agree with grumpy. The calculation preceeding the check for a whole number could be introducing far more error than just making it a little off from a whole number when logically it should be equal to a whole number.

Consider starting with a double value of 2^50+0.5 and then looping 1 million times, adding 0.0000005 each iteration. Clearly mathematics will tell you that the result should be 2^50+1 exactly. However the computer scientist in you knows that the result will be 2^50+0.5 since each addition of 0.0000005 will have no effect as the magnitudes are too different.
To be consistent you're earlier statement, you'd be claiming that the variable which now holds a number exactly half way between to whole numbers should be detected as being a whole number.

All grumpy is saying is that the point at which a variable is a no longer whole number must be considered to be where calculations to obtain its value introduce the inaccuracy, and not where the actual test is performed.

Afterall, if I then deleted the loop described above and just went straight for the whole number test, I'd be testing a variable holding the exact same value (same bit pattern of ones and zeros in memory), yet you'd desire a different result when the loop is omitted. That simply isn't possible.

11. Originally Posted by Daved
You're telling me that (1000.43 - 1000.00)*100 is not a whole number?
I didn't tell you that but, yes, it will work out that way if the expression (1000.43 - 1000.00)*100 is computed using floating point.

Floating point calculations introduce errors due to finite rounding/precision. To start with, negative powers of 10 cannot be represented exactly in binary, so 1000.43 will not be represented exactly. And the errors will propagate from there with floating point operations (addition, multiplication of values, etc)
Originally Posted by Daved
I'm sure you can understand the point that I was making. If you'd like to address that feel free, but your comments don't make sense in the context of my original advice, which I still think is important for the OP to understand.
I understood your point, but I consider you're mistaken. iMalc has captured my meaning perfectly.

12. I understand the potential for rounding/accuracy errors in floating point calculations. That is what I was warning about.

If you write a program and ask the user to enter three numbers a, b, c. Your program promises to tell the user whether (a-b)*c is a whole number. The user enters 1000.43, 1000.00 and 100. You output: "Sorry, (a-b)*c is not a whole number because I use floating point computations which aren't always accurate." Of course not.

iMalc's example is irrelevant unless you think it means that the advice in 29.17 of the C++ FAQ Lite should never be followed. Is that what you're arguing? I doubt it. There are times when using == to compare floating point numbers leads to inaccurate results. You can adjust for that. This is one of those cases.

Just because there are other potential errors in floating point calculations doesn't mean you should ignore one that can be combated. Just because your adjustment won't fix all possible problems doesn't mean you shouldn't fix as many of them as you reasonably can.

>> All grumpy is saying is that the point at which a variable is a no longer whole number must
>> be considered to be where calculations to obtain its value introduce the inaccuracy, and not
>> where the actual test is performed.

I disagree. It should be the point at which you can no longer reasonably account for the inaccuracy. Using a decent epsilon value will reduce many of these errors and greatly improve the accuracy of the whole number check.

13. If you write a program and ask the user to enter three numbers a, b, c. Your program promises to tell the user whether (a-b)*c is a whole number. The user enters 1000.43, 1000.00 and 100. You output: "Sorry, (a-b)*c is not a whole number because I use floating point computations which aren't always accurate." Of course not.
What if the user enters 1000.42999999994381, 1000.00 and 100?

14. >> What if the user enters 1000.42999999994381, 1000.00 and 100?

Just because your adjustment won't fix all possible problems doesn't mean you shouldn't fix as many of them as you reasonably can.

15. Originally Posted by Daved
It should be the point at which you can no longer reasonably account for the inaccuracy. Using a decent epsilon value will reduce many of these errors and greatly improve the accuracy of the whole number check.
Actually I think that's fair enough too.

I think in most cases a test such as this would ususally be used directly after inputting a value from the user, where the point is of course moot.