Checking if float is an integer

CFloating PointInt

C Problem Overview


How can I check if a float variable contains an integer value? So far, I've been using:

float f = 4.5886;
if (f-(int)f == 0)
     printf("yes\n");
else printf("no\n");

But I wonder if there is a better solution, or if this one has any (or many) drawbacks.

C Solutions


Solution 1 - C

Apart from the fine answers already given, you can also use ceilf(f) == f or floorf(f) == f. Both expressions return true if f is an integer. They also returnfalse for NaNs (NaNs always compare unequal) and true for ±infinity, and don't have the problem with overflowing the integer type used to hold the truncated result, because floorf()/ceilf() return floats.

Solution 2 - C

Keep in mind that most of the techniques here are valid presuming that round-off error due to prior calculations is not a factor. E.g. you could use roundf, like this:

float z = 1.0f;

if (roundf(z) == z) {
    printf("integer\n");
} else {
    printf("fraction\n");
}

The problem with this and other similar techniques (such as ceilf, casting to long, etc.) is that, while they work great for whole number constants, they will fail if the number is a result of a calculation that was subject to floating-point round-off error. For example:

float z = powf(powf(3.0f, 0.05f), 20.0f);

if (roundf(z) == z) {
    printf("integer\n");
} else {
    printf("fraction\n");
}

Prints "fraction", even though (31/20)20 should equal 3, because the actual calculation result ended up being 2.9999992847442626953125.

Any similar method, be it fmodf or whatever, is subject to this. In applications that perform complex or rounding-prone calculations, usually what you want to do is define some "tolerance" value for what constitutes a "whole number" (this goes for floating-point equality comparisons in general). We often call this tolerance epsilon. For example, lets say that we'll forgive the computer for up to +/- 0.00001 rounding error. Then, if we are testing z, we can choose an epsilon of 0.00001 and do:

if (fabsf(roundf(z) - z) <= 0.00001f) {
    printf("integer\n");
} else {
    printf("fraction\n");
}

You don't really want to use ceilf here because e.g. ceilf(1.0000001) is 2 not 1, and ceilf(-1.99999999) is -1 not -2.

You could use rintf in place of roundf if you prefer.

Choose a tolerance value that is appropriate for your application (and yes, sometimes zero tolerance is appropriate). For more information, check out this article on comparing floating-point numbers.

Solution 3 - C

if (fmod(f, 1) == 0.0) {
  ...
}

Don't forget math.h and libm.

Solution 4 - C

stdlib float modf (float x, float *ipart) splits into two parts, check if return value (fractional part) == 0.

Solution 5 - C

if (f <= LONG_MIN || f >= LONG_MAX || f == (long)f) /* it's an integer */

Solution 6 - C

This deals with computational round-off. You set the epsilon as desired:

bool IsInteger(float value)
{
    return fabs(ceilf(value) - value) < EPSILON;
}

Solution 7 - C

I'm not 100% sure but when you cast f to an int, and subtract it from f, I believe it is getting cast back to a float. This probably won't matter in this case, but it could present problems down the line if you are expecting that to be an int for some reason.

I don't know if it's a better solution per se, but you could use modulus math instead, for example: float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true; depending on your compiler you may or not need the .0 after the 1, again the whole implicit casts thing comes into play. In this code, the bool isInt should be true if the right of the decimal point is all zeroes, and false otherwise.

Solution 8 - C

#define twop22 (0x1.0p+22)
#define ABS(x) (fabs(x))
#define isFloatInteger(x) ((ABS(x) >= twop22) || (((ABS(x) + twop22) - twop22) == ABS(x)))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionsidyllView Question on Stackoverflow
Solution 1 - CMarc Mutz - mmutzView Answer on Stackoverflow
Solution 2 - CJason CView Answer on Stackoverflow
Solution 3 - CIgnacio Vazquez-AbramsView Answer on Stackoverflow
Solution 4 - CDavidNView Answer on Stackoverflow
Solution 5 - CR.. GitHub STOP HELPING ICEView Answer on Stackoverflow
Solution 6 - CJiminionView Answer on Stackoverflow
Solution 7 - CControllerfaceView Answer on Stackoverflow
Solution 8 - CkannaView Answer on Stackoverflow