vehomzzz
vehomzzz

Reputation: 44578

Check double variable if it contains an integer, and not floating point

What I mean is the following:

double d1 = 555;
double d2 = 55.343;

I want to be able to tell that d1 is an integer while d2 is not. Is there an easy way to do it in C/C++?

Upvotes: 55

Views: 62168

Answers (17)

Gkcrafting
Gkcrafting

Reputation: 36

I created my own algorithm for that.

bool isDoubleAnInt(double v) {
    return !((v - (int64_t) floor(v)) > 0);
}

I know it's not the most short and efficient way, but it's my way to do it.

Upvotes: 0

user2226755
user2226755

Reputation: 13157

modf uses std::nearbyint(num) that why you should use nearbyint which return a double without decimal and may be faster.

#include <iostream>
#include <cmath>

int main() {
    double      number = 55.12;

    if (!(number - std::nearbyint(number))) {
      std::cout << "Is integer!";
    } else {
      std::cout << "Has decimal!";
    }
    
    return 0;
}

Upvotes: 1

Mayur Agarwal
Mayur Agarwal

Reputation: 1814

Just compare ceil and floor value of d

return floor(d)==ceil(d);

So, for d1=555, the above statement will return 555==555, i.e, true, so it's an integer.

And for d2=555.6, the above statement will return 555==556, i.e, false, so it's a double.

Upvotes: 5

user15942888
user15942888

Reputation: 11

#define _EPSILON_ 0.000001

bool close_to_int(double &d)
{
    double integer,
           fraction = modf(d, &integer);
    if(fraction < _EPSILON_)
    {
        d = integer;
        return true;
    }
    if((1.0 - fraction) < _EPSILON_)
    {
        d = integer + 1;
        return true;
    }
    return false;
}

This looks at both side of the integer value and sets the value of d if it is within the limits of an integer value.

Upvotes: 1

Stephen Canon
Stephen Canon

Reputation: 106167

Assuming a c99 and IEEE-754 compliant environment,

(trunc(x) == x)

is another solution, and will (on most platforms) have slightly better performance than modf because it needs only to produce the integer part. Both are completely acceptable.

Note that trunc produces a double-precision result, so you don't need to worry about out of range type conversions as you would with (int)x.


Edit: as @pavon points out in a comment, you may need to add another check, depending on whether or not you care about infinity, and what result you want to get if x is infinite.

Upvotes: 21

DigitalRoss
DigitalRoss

Reputation: 146063

int iHaveNoFraction(double d){
    return d == trunc(d);
}

Now, it wouldn't be C if it didn't have about 40 years of language revisions...

In C, == returns int but in C++ it returns bool. At least on my Linux distro (Ubuntu) you need to either declare double trunc(double); or you could compile with -std=c99, or declare the level macro, all in order to get <math.h> to declare it.

Upvotes: 4

Denis
Denis

Reputation: 1534

I faced a similar questions. As I needed to round the double anyway, that's what I find working:

double d = 2.000000001;
int i = std::round(d);
std::fabs(d-i) < 10 * std::numeric_limits<double>::epsilon()

Upvotes: -1

avakar
avakar

Reputation: 32635

Use std::modf:

double intpart;
modf(value, &intpart) == 0.0

Don't convert to int! The number 1.0e+300 is an integer too you know.

Edit: As Pete Kirkham points out, passing 0 as the second argument is not guaranteed by the standard to work, requiring the use of a dummy variable and, unfortunately, making the code a lot less elegant.

Upvotes: 98

Jeroen Dirks
Jeroen Dirks

Reputation: 7877

In many calculations you know that your floating point results will have a small numerical error that can result from a number of multiplications.

So what you may really want to find is the question is this number within say 1e-5 of an integer value. In that case I think this works better:

bool isInteger( double value )
{
    double flr = floor( value + 1e-5 );
    double diff = value - flr;
    return diff < 1e-5;
}

Upvotes: -1

KJP
KJP

Reputation: 541

Below you have the code for testing d1 and d2 keeping it very simple. The only thing you have to test is whether the variable value is equal to the same value converted to an int type. If this is not the case then it is not an integer.

#include<iostream>
using namespace std;

int main()
{
    void checkType(double x);
    double d1 = 555;
    double d2 = 55.343;        
    checkType(d1);
    checkType(d2);
    system("Pause");
    return 0; 
}
void checkType(double x)
{
     if(x != (int)x)
     {
          cout<< x << " is not an integer "<< endl;
     }
     else 
     {
         cout << x << " is an integer " << endl;
     }
};

Upvotes: -2

Pete Kirkham
Pete Kirkham

Reputation: 49311

avakar was almost right - use modf, but the detail was off.

modf returns the fractional part, so the test should be that the result of modf is 0.0.

modf takes two arguments, the second of which should be a pointer of the same type as the first argument. Passing NULL or 0 causes a segmentation fault in the g++ runtime. The standard does not specify that passing 0 is safe; it might be that it happens to work on avakar's machine but don't do it.

You could also use fmod(a,b) which calculates the a modulo b passing 1.0. This also should give the fractional part.

#include<cmath>
#include<iostream>

int main ()
{
    double d1 = 555;
    double d2 = 55.343;

    double int_part1;
    double int_part2;

    using namespace std;

    cout << boolalpha;
    cout << d1 << " " << modf ( d1, &int_part1 ) << endl;
    cout << d1 << " " << ( modf ( d1, &int_part1 ) == 0.0 ) << endl;
    cout << d2 << " " << modf ( d2, &int_part2 ) << endl;
    cout << d1 << " " << ( modf ( d2, &int_part2 ) == 0.0 ) << endl;
    cout << d2 << " " << modf ( d2, &int_part2 ) << endl;
    cout << d1 << " " << ( modf ( d2, &int_part2 ) == 0.0 ) << endl;

    cout << d1 << " " << fmod ( d1, 1.0 ) << endl;
    cout << d1 << " " << ( fmod ( d1, 1.0 ) == 0 ) << endl;
    cout << d2 << " " << fmod ( d2, 1.0 ) << endl;
    cout << d2 << " " << ( fmod ( d2, 1.0 ) == 0 ) << endl;


    cout.flush();

    modf ( d1, 0 ); // segfault

}

Upvotes: 7

TJ L
TJ L

Reputation: 24462

Assuming you have the cmath <math.h> library, you can check the number against it's floor. If the number might be negative, make sure you get the absolute first.

bool double_is_int(double trouble) {
   double absolute = abs( trouble );
   return absolute == floor(absolute);
}

Upvotes: 8

Ashwin
Ashwin

Reputation: 3637

How about this?

if ((d1 - (int)d1) == 0)
    // integer

Upvotes: 0

Kirill V. Lyadvinsky
Kirill V. Lyadvinsky

Reputation: 99585

#include <math.h>
#include <limits>

int main()
{
  double x, y, n;
  x = SOME_VAL;
  y = modf( x, &n ); // splits a floating-point value into fractional and integer parts
  if ( abs(y) < std::numeric_limits<double>::epsilon() )
  {
    // no floating part
  }
}

Upvotes: -1

DVK
DVK

Reputation: 129403

How about

if (abs(d1 - (round(d1))) < 0.000000001) {
   printf "Integer\n"; /* Can not use "==" since we are concerned about precision */
}

Fixed up to work using rounding to reflect bug Anna found

Alternate solutions:

if ((d1 - floor(d1) < 0.000000001) || (d1 - floor(d1) > 0.9999999999)) {
   /* Better store floor value in a temp variable to speed up */
   printf "Integer\n"; /* Can not use "==" since we are concerned about precision */
}

Theres also another one with taking floor, subtracting 0.5 and taking abs() of that and comparing to 0.499999999 but I figure it won't be a major performance improvement.

Upvotes: 2

Patrice Bernassola
Patrice Bernassola

Reputation: 14426

try:

bool isInteger(double d, double delta)
{
   double absd = abs(d);

   if( absd - floor(absd) > 0.5 )
      return (ceil(absd) - absd) < delta;

   return (d - floor(absd)) < delta;
}

Upvotes: 0

VNarasimhaM
VNarasimhaM

Reputation: 1570

A sample code snipped that does it:

if (  ABS( ((int) d1) - (d1)) )< 0.000000001) 

 cout <<"Integer" << endl;

else

 cout <<"Flaot" << endl;

EDIT: Changed it to reflect correct code.

Upvotes: -2

Related Questions