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++?
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++?
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.
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.
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 compile with -std=c99
, or declare the level macro, all in order to get <math.h>
to declare it.
int i = d1;
return d1 == ((double) i);
The cast probably isn't necessary, but makes it a bit clearer whats going on.
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);
}
Use modf
:
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.
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;
}
#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
}
}
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
}
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;
}
};
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
.