Я имею в виду следующее:
double d1 =555;
double d2=55.343
Я хочу сказать, что d1 является целым числом, а d2 - нет. Есть ли простой способ сделать это в c/С++?
Я имею в виду следующее:
double d1 =555;
double d2=55.343
Я хочу сказать, что d1 является целым числом, а d2 - нет. Есть ли простой способ сделать это в c/С++?
Используйте std::modf
:
double intpart;
modf(value, &intpart) == 0.0
Не конвертируйте в int
! Число 1.0e+300
- это целое число, которое вы знаете.
Изменить: как указывает Пит Киркхам, передавая 0, поскольку второй аргумент не гарантируется стандартом для работы, требующим использования фиктивной переменной и, к сожалению, делает код намного менее изящным.
Предполагая, что у вас есть библиотека cmath <math.h>
, вы можете проверить число против нее floor. Если число может быть отрицательным, убедитесь, что вы сначала получили absolute.
bool double_is_int(double trouble) {
double absolute = abs( trouble );
return absolute == floor(absolute);
}
Предполагая среду c99 и IEEE-754,
(trunc(x) == x)
- это еще одно решение и будет (на большинстве платформ) иметь немного лучшую производительность, чем modf
, потому что ему нужно только создать целую часть. Оба полностью приемлемы.
Обратите внимание, что trunc
создает результат с двойной точностью, поэтому вам не нужно беспокоиться о преобразованиях вне диапазона, как это было бы с (int)x
.
Изменить: если в комментарии указано @pavon, вам может потребоваться добавить еще одну проверку, в зависимости от того, заботитесь о бесконечности или нет, и какой результат вы хотите получить, если x
бесконечно.
Как насчет
if (abs(d1 - (round(d1))) < 0.000000001) {
printf "Integer\n"; /* Can not use "==" since we are concerned about precision */
}
Исправлено для работы с округлением, чтобы отразить ошибку, найденную Анной.
Альтернативные решения:
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 также еще один, занимающий пол, вычитая 0,5 и принимая abs() этого и сравнивая с 0.499999999, но я полагаю, что это не будет основным улучшением производительности.
int iHaveNoFraction(double d){
return d == trunc(d);
}
Теперь это было бы не C, если бы у него не было примерно 40 лет языковых версий...
В C, ==
возвращает int
, но в С++ он возвращает bool
. По крайней мере, на моем Linux-дистрибутиве (Ubuntu) вам нужно либо объявить double trunc(double);
, либо вы можете скомпилировать с помощью -std=c99
или объявить макрос уровня, чтобы получить <math.h>
, чтобы объявить его.
avakar был почти прав - используйте modf, но деталь была выключена.
modf возвращает дробную часть, поэтому тест должен состоять в том, что результат modf равен 0.0.
modf принимает два аргумента, второй из которых должен быть указателем того же типа, что и первый аргумент. Передача NULL или 0 вызывает ошибку сегментации в среде выполнения g++. В стандарте не указывается, что передача 0 безопасна; возможно, это работает на машине Авакара, но не делайте этого.
Вы также можете использовать fmod(a,b)
, который вычисляет a
modulo b
, проходящий 1.0. Это также должно дать дробную часть.
#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
}
#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
}
}
Как насчет этого?
if ((d1 - (int)d1) == 0)
// integer
попробовать:
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;
}
Ниже приведен код для тестирования d1 и d2, который очень прост. Единственное, что вам нужно проверить, - это значение переменной равно тому же значению, преобразованному в тип int. Если это не так, то это не целое число.
#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;
}
};
Во многих вычислениях вы знаете, что ваши результаты с плавающей запятой будут иметь небольшую числовую ошибку, которая может возникнуть в результате нескольких умножений.
Так что вы действительно можете найти, так это вопрос в том, что это число в пределах 1е-5 целочисленного значения. В этом случае я думаю, что это работает лучше:
bool isInteger( double value )
{
double flr = floor( value + 1e-5 );
double diff = value - flr;
return diff < 1e-5;
}
У меня возникли аналогичные вопросы. Поскольку мне все равно нужно было обойти двойник, то, что я нахожу, работает:
double d = 2.000000001;
int i = std::round(d);
std::fabs(d-i) < 10 * std::numeric_limits<double>::epsilon()
Скомпилированный пример кода:
if ( ABS( ((int) d1) - (d1)) )< 0.000000001)
cout <<"Integer" << endl;
else
cout <<"Flaot" << endl;
EDIT: Изменено, чтобы отобразить правильный код.