Skip to main content
GameDev.net gamedev.net
🔒 Locked

Is number an integer?

Started by Frogget Dec 22, 2004 at 11:04 AM 13 replies 1.7k views
Original Post
Frogget
Frogget
Does anyone know of a way of checking if a floating-point number is an integer without converting the float to an int? The best way I can think of for checking this is: float num; if (num - (int)num == 0) I'm doing this in an inner loop, so I'd like to do it without the float-to-int conversion.
Puzzler183
Puzzler183
That's probably the fastest way although the catch is that you have to check if it's within a certain small range of its floor and its ceiling (your method leaves out things like 4.99 since it will be truncated). For example:

#define FLOAT_EPSILON 0.00001if (fabs(num - floor(num)) < FLOAT_EPSILON ||    fabs(num - ceil(num)) < FLOAT_EPSILON){    //It's an integer}


Decreasing FLOAT_EPSILON forces it to be closer and closer to an integer.
grhodes_at_work
grhodes_at_work
Why not just check and see if floor(num) == ceil(num)? Wouldn't that be true only if the number were an integer? I think it would for the C++ library version of the ceil and floor functions. Of course, if you really need the tolerance, e.g., some slight error is allowed, you'd have to go with Mr. 183's suggestion.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
ToohrVyk
ToohrVyk
By the way, isn't there an exponent trick to check if a number is an exact integer, based on the IEEE float specification? For instance, if the exponent is above 127 the number is clearly an integer, below 104 it can't be, with a check on the mantissa if it falls in-between.
Puzzler183
Puzzler183
Quote:
Original post by grhodes_at_work
Why not just check and see if floor(num) == ceil(num)? Wouldn't that be true only if the number were an integer? I think it would for the C++ library version of the ceil and floor functions. Of course, if you really need the tolerance, e.g., some slight error is allowed, you'd have to go with Mr. 183's suggestion.


That won't work unless you are exactly at an integer... For example, 3.0001 will be false while it may be within the tolerances. If you want something with no tolerances then that definitely works.

Quote:
Original post by ToohrVyk
By the way, isn't there an exponent trick to check if a number is an exact integer, based on the IEEE float specification? For instance, if the exponent is above 127 the number is clearly an integer, below 104 it can't be, with a check on the mantissa if it falls in-between.


Yeah... But that's not cross platform and gets tricky.
Motorherp
Motorherp
I've not got a suggestion but just because no-one else has pointed this out yet.

You really don't want to get in the habit of casting floats to ints. Very very slow.
[size="1"] [size="4"]:: SHMUP-DEV ::
Fruny
Fruny
Quote:
Original post by ToohrVyk
By the way, isn't there an exponent trick to check if a number is an exact integer, based on the IEEE float specification? For instance, if the exponent is above 127 the number is clearly an integer, below 104 it can't be, with a check on the mantissa if it falls in-between.


bool is_integer(float f){  const unsigned int m_bits = 23;  const unsigned int e_bits = 8;  const unsigned int e_bias = 127;  const unsigned int e_mask = (1 << e_bits) - 1;  const unsigned int m_mask = (1 << m_bits) - 1;  union  {    unsigned int i;    float f;  } u;  u.f = f;  const int exp = (u.i >> m_bits) & e_mask;  if (exp < e_bias)     return f == 0;  if (exp > e_bias + m_bits)     return exp != e_mask;  const unsigned int mask = m_mask >> (exp-e_bias);  return (u.i & mask) == 0;}
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
kSquared
kSquared
edit: D'uh. Puzzler183's post amounts to the same thing (though I think my solution is a little bit clearer, and doesn't require a call to fabs). Sorry about that.

Quote:
Original post by Puzzler183
Quote:
Original post by grhodes_at_work
Why not just check and see if floor(num) == ceil(num)? Wouldn't that be true only if the number were an integer? I think it would for the C++ library version of the ceil and floor functions. Of course, if you really need the tolerance, e.g., some slight error is allowed, you'd have to go with Mr. 183's suggestion.


That won't work unless you are exactly at an integer... For example, 3.0001 will be false while it may be within the tolerances. If you want something with no tolerances then that definitely works.

If your tolerance is some epsilon < 0.5, then floor(n + epsilon) == ceil(n - epsilon) should return true if there exists an integer on the interval [n - epsilon, n + epsilon]. Proof by exhaustion:

Case I: Not within tolerances.

    a           n-e    n   n+e    a+1<---|------------(-----*-----)-----|--------------->   floor(n)                       ceil(n)floor(n+e) = aceil(n-e)  = a+1


floor(n+e) != ceil(n-e), which is the correct behavior.

Case II: n+e is near an integer.

    a           n-e    n   n+e    <---|------------(-----*--|--)-------------------->   floor(n)              ceil(n)floor(n+e) = a+1ceil(n-e)  = a+1


floor(n+e) == ceil(n-e), which is the correct behavior.

Case III: n-e is near an integer.

                n-e    n   n+e    a+1<----------------(-|---*-----)-----|--------------->                  floor(n)        ceil(n)floor(n+e) = aceil(n-e)  = a


floor(n+e) == ceil(n-e), which is the correct behavior.

This should work for any epsilon < 0.5. As for whether Fruny's method of checking the exponent, I'm not sure which way is faster. I guess it depends on the floor/ceil implementations.
- k2 "Choose a job you love, and you'll never have to work a day in your life." — Confucius"Logic will get you from A to B. Imagination will get you everywhere." — Albert Einstein"Money is the most egalitarian force in society. It confers power on whoever holds it." — Roger Starr{General Programming Forum FAQ<
Dmytry
Dmytry
Just
if(a-floor(a) < tolerance)

....You people are truly amazing....
Puzzler183
Puzzler183
Quote:
Original post by Dmytry
Just
if(a-floor(a) < tolerance)

....You people are truly amazing....


No, that really won't work. For 3.99 it will say that 3.99 - 3 = .99 which won't be less than your tolerance.
Dmytry
Dmytry
Quote:
Original post by Puzzler183
Quote:
Original post by Dmytry
Just
if(a-floor(a) < tolerance)

....You people are truly amazing....


No, that really won't work. For 3.99 it will say that 3.99 - 3 = .99 which won't be less than your tolerance.

ops, sorry.
(late very merry christmas night there)

if(a-floor(a+tolerance)must work.
kSquared
kSquared
Quote:
Original post by Dmytry
Quote:
Original post by Puzzler183
Quote:
Original post by Dmytry
Just
if(a-floor(a) < tolerance)

....You people are truly amazing....


No, that really won't work. For 3.99 it will say that 3.99 - 3 = .99 which won't be less than your tolerance.

ops, sorry.
(late very merry christmas night there)

if(a-floor(a+tolerance)must work.


Dmytry, I think you missed the first line of my post. ;)
- k2 "Choose a job you love, and you'll never have to work a day in your life." — Confucius"Logic will get you from A to B. Imagination will get you everywhere." — Albert Einstein"Money is the most egalitarian force in society. It confers power on whoever holds it." — Roger Starr{General Programming Forum FAQ<
ajas95
ajas95
Quote:
Original post by Motorherp
You really don't want to get in the habit of casting floats to ints. Very very slow.


Float-int conversion is NOT slow... what is slow is that the processor has several different rounding modes -- So to cast float-int, the compiler generates instructions to read the current rounding mode and save it, switch to "round-toward-zero" mode, perform the conversion, then restore the original rounding mode.

So my question is, why not just simply set the rounding mode? Why go to all the trouble of saving and restoring? It seems totally unneccessary.

Well, anyway. Likely this is not the bottleneck in your code.
Dmytry
Dmytry
Quote:
Original post by kSquared
Quote:
Original post by Dmytry
Quote:
Original post by Puzzler183
Quote:
Original post by Dmytry
Just
if(a-floor(a) < tolerance)

....You people are truly amazing....


No, that really won't work. For 3.99 it will say that 3.99 - 3 = .99 which won't be less than your tolerance.

ops, sorry.
(late very merry christmas night there)

if(a-floor(a+tolerance)must work.


Dmytry, I think you missed the first line of my post. ;)

?
you are using floor and ceil.
if(a-floor(a+tolerance)is not same, and works.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.