Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checking if float is an integer

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.

like image 480
sidyll Avatar asked Apr 26 '11 22:04

sidyll


People also ask

How do you check if a number is integer or not?

To check if a String contains digit character which represent an integer, you can use Integer. parseInt() . To check if a double contains a value which can be an integer, you can use Math. floor() or Math.

Can you compare floats to integers?

Assigning an integer to float and comparison in C/C++ The integer is a data type used to define a number that contains all positive, negative or zero non-fractional values. These cannot have decimals. Float is a data type used to define a number that has a fractional value. These can have decimals also.


2 Answers

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.

like image 137
Marc Mutz - mmutz Avatar answered Sep 19 '22 13:09

Marc Mutz - mmutz


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.

like image 34
Jason C Avatar answered Sep 17 '22 13:09

Jason C