# Thread: How can I test if something is an integer or not?

1. Originally Posted by robatino
I believe an integer of sufficiently small absolute value can be represented exactly as a floating-point type of given size. For example, an IEEE 754 32-bit float uses 23 bits for the mantissa (and 8 for the exponent, and 1 for the sign bit), and 2^23 is roughly 8 million, so I believe integers between roughly plus and minus 4 million can be represented exactly as such a float. In this case, it would be okay to use ==. If that's not enough precision, an IEEE 754 64-bit double uses (52, 11, 1) bits for the 3 fields, so should be able to represent integers between roughly plus and minus 2^51.
You believe wrong

2. Would you mind elaborating a bit (explaining exactly which statement is wrong, and why)?.

3. you should search the forum - it was discussed several times why == cannot be used with floats

even float a=1.0
and double b=1.0 can be represented differently

First of all they'll be probably stored as
0.1*10^1
Then you should convert 0.1 into the binary format and see if it will have the same representetion in different number of bits...
Then convert back and see if this number is still 1

4. For a double variable x one can also compare x with either floor(x) or ceil(x) in <math.h> using == to see if the fractional part is zero. Although for this to work, one must assume that the double type has enough extra precision left over from representing the integer part to be able to at least tell if the fractional part is nonzero or not. I think this can only be done reliably by knowing something about the specific problem. But the "delta" method has the same problem - one has to use such knowledge in order to choose delta. It's not enough to just set it to machine precision, if that precision isn't enough.

5. Originally Posted by vart
you should search the forum - it was discussed several times why == cannot be used with floats

even float a=1.0
and double b=1.0 can be represented differently

First of all they'll be probably stored as
0.1*10^1
Then you should convert 0.1 into the binary format and see if it will have the same representetion in different number of bits...
Then convert back and see if this number is still 1
OK, I understand now - if the number is normalized so the mantissa represents a number between 0 and 1, then that number has to be exactly representable in binary, which it probably won't be. This issue will also invalidate my later suggestion of comparing with floor() or ceil().

6. Actually, upon further thought, I think you're wrong here - I believe the normalization is by a power of 2, not a power of 10. This means that it would not prevent an integer of sufficiently small absolute value from being represented exactly. For example, see

http://en.wikipedia.org/wiki/Floatin...ice_properties

although it's a bit wrong when it says "any integer less than or equal to" without mentioning absolute value.

When you write
a = 1.0 - the value of 1 is never stored as is.
Some float operations are applied.
When you print the value stored - some other operations are applied.

When float arithmetics is applied you cannot be sure that 1/2.0*2.0 == 1.
Never.

So you never use == for floats.

It is simple.

8. I'd agree with vart. There's no guarantees as far as floating point arithmetic goes.

9. This means that it would not prevent an integer of sufficiently small absolute value from being represented exactly.
Yes, often type double can accurately represent even more integer values than a plain int, but it's not required. You can check float.h for info like DBL_MANT_DIG and others.

When float arithmetics is applied you cannot be sure that 1/2.0*2.0 == 1
That's a different point. Whilst it's probably possible to accurately represent the values of 0.5 and/or 1 in a float/double, whether or not the computation result in those values is another matter. If the above calculation was more complex, possible answers could be anywhere between 0.99..... and 1.00...1, which may become 0 or 1, if converted to int.

Nevertheless, as stated above, in many cases, you could store an integer (i.e. 5) in a double and retrieve the same integer value later. I.e. it would not turn into 4.9999999 on many implementations.

10. If the machine uses IEEE 754 arithmetic (which is not guaranteed by the standard, but which is true on most platforms), then one can be sure that 1/2.0*2.0 == 1, or that any integer of sufficiently small absolute value can be represented exactly. For example, consider the following program to test a double to see if it's an integer (I wrote this in C++ but it's easy to convert):
Code:
```#include <iostream>
#include <cmath>

int main() {
double d;
while (true) {
std::cout << "Input double number d:";
std::cin >> d;
if (d == floor(d)) std::cout << "d is an integer\n";
else std::cout << "d is not an integer\n";
}
}```
I used the dreaded "==". It works for inputs up to about 15 or 16 decimal digits, assuming the arithmetic is IEEE 754 (if the input is longer than that, it thinks it's always an integer). Suppose I modified it to use the delta method (either on the difference between d and floor(d), or the difference between 1 and d/floor(d)). Okay, how do I choose delta? Is there a portable way? No. My point is that this is a special case, and the general rule "never use == for floats" doesn't necessarily apply.

11. how do I choose delta?
It's often a percentage of (one of) the numbers you're trying to compare. Thus it would vary automatically depending on whether the number is 0.0000324 or 3x10^56.

then one can be sure that 1/2.0*2.0 == 1
That doesn't prove anything, the equation is far too simple. See code below for another equation.

In your test program, you're taking a value from stdin, which is different than actually computing one. Often, a calculation will not result in the actual correct value, even though that correct value can be represented. So a calculation might result in 0.99999, when it should result in 1.

Code:
```#include <stdio.h>

int main(void) {
int i;
double a=1, b=1, c=1;
for(i=0; i<10000; i++) {
if( (a+b)*c / (a*c + b*c) == 1 )
;  /* success */
else
printf("Failed at i=%d\n", i);
a *= 1.001; b += 0.05; c *= 0.9998;
}
return 0;
}```
Note that the test will fail even at very low values of i (far before a,b or c can no longer be represented accurately. Try it with long double too if you wish).

12. I agree that in the general case, comparing two arbitrary floating-point numbers using == is bad (as your code shows). Actually, 1.001, 0.05, and 0.9998 can't be represented accurately, so the expression will be inexact as soon as i == 1. For example, 0.05 equals 1/20 = 1/4 * 1/5 and 1/5 can't be represented accurately. On my machine it fails first at i=4.

Edit: And if the original poster's floating-point expression comes from some similar general expression, then there's no reliable way to determine if it's an integer or not, without using some problem-specific knowledge - just because there's no general way to know how close the expression could be to an integer without actually being one. One way is to try to establish a lower bound delta on how close it could be, and then use the delta method. But even that doesn't work in all cases, since there are situations where the difference could be arbitrarily small without being zero (for example, the value of 1/n gets arbitrarily close to 0 as n -> infinity, but never equals it).

13. Actually, 1.001, 0.05, and 0.9998 can't be represented accurately
Yes, you're right. Bad choice of values on my behalf.

Anyways, despite all of this now being rather unrelated to the original post, I'll post some code, which I wrote some time ago, to look at the computer's float representation. It relies on some technically undefined behaviour with regards to union usage, in order to get the representation. It's unlikely that it will work incorrectly.

Code:
```#include <stdio.h>

union float_or_representation {
float f;
unsigned int rep;
};

typedef struct {
union float_or_representation f_or_rep;
int sign;
int exponent;
int mantissa;
char binary[33];
} float_internals;

void uncover_float(float_internals *internals) {
int i = 0;
unsigned int temp = internals->f_or_rep.rep; /* technically undefined behaviour */
/* SIGN */
if(temp & 2147483648u) {
internals->sign = -1;
internals->binary[i] = '1';
} else {
internals->sign = 1;
internals->binary[i] = '0';
}
temp = temp << 1;

/* EXPONENT */
for(i=1, internals->exponent=0; i<=8; i++) {
if(temp & 2147483648u) {
internals->binary[i] = '1';
internals->exponent = internals->exponent * 2 + 1;
} else {
internals->binary[i] = '0';
internals->exponent *= 2;
}
temp = temp << 1;
}
internals->exponent -= 127; /* Offset Adjust */

/* MANTISSA */
for(i=9, internals->mantissa=0; i<=31; i++) {
if(temp & 2147483648u) {
internals->binary[i] = '1';
internals->mantissa = internals->mantissa * 2 + 1;
} else {
internals->binary[i] = '0';
internals->mantissa *= 2;
}
temp = temp << 1;
}

internals->binary[i] = '\0';

/* NOTE: We don't cover special cases (i.e. 0, infinity, NaN...) */
}

int main(void) {
float_internals internals;

internals.f_or_rep.f = 0.05; /* set any float */
uncover_float(&internals);   /* analyze float */

printf("Float: %f is represnted as %s\n  Sign: %d [-1 or 1]\n  Exponent: %d\n  Mantissa (numerator): %d\n",
internals.f_or_rep.f, internals.binary, internals.sign, internals.exponent, internals.mantissa);
printf("You can calculate the float by: float = Sign * 2^Exponent * (1 + Mantissa (numerator) / 8388608)\n"
"Special Cases not covered (i.e. 0, NaN, infinity...)\n");
return 0;
}```

14. Originally Posted by vart

When you write
a = 1.0 - the value of 1 is never stored as is.
Some float operations are applied.
When you print the value stored - some other operations are applied.

When float arithmetics is applied you cannot be sure that 1/2.0*2.0 == 1.
Never.

So you never use == for floats.

It is simple.