Reputation: 44578
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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