Подтвердить что ты не робот

Проверьте двойную переменную, если она содержит целое число, а не с плавающей запятой

Я имею в виду следующее:

  double d1 =555;
  double d2=55.343

Я хочу сказать, что d1 является целым числом, а d2 - нет. Есть ли простой способ сделать это в c/С++?

4b9b3361

Ответ 1

Используйте std::modf:

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

Не конвертируйте в int! Число 1.0e+300 - это целое число, которое вы знаете.

Изменить: как указывает Пит Киркхам, передавая 0, поскольку второй аргумент не гарантируется стандартом для работы, требующим использования фиктивной переменной и, к сожалению, делает код намного менее изящным.

Ответ 2

Предполагая, что у вас есть библиотека cmath <math.h>, вы можете проверить число против нее floor. Если число может быть отрицательным, убедитесь, что вы сначала получили absolute.

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

Ответ 3

Предполагая среду c99 и IEEE-754,

(trunc(x) == x)

- это еще одно решение и будет (на большинстве платформ) иметь немного лучшую производительность, чем modf, потому что ему нужно только создать целую часть. Оба полностью приемлемы.

Обратите внимание, что trunc создает результат с двойной точностью, поэтому вам не нужно беспокоиться о преобразованиях вне диапазона, как это было бы с (int)x.


Изменить: если в комментарии указано @pavon, вам может потребоваться добавить еще одну проверку, в зависимости от того, заботитесь о бесконечности или нет, и какой результат вы хотите получить, если x бесконечно.

Ответ 4

Как насчет

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, но я полагаю, что это не будет основным улучшением производительности.

Ответ 5

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

Теперь это было бы не C, если бы у него не было примерно 40 лет языковых версий...

В C, == возвращает int, но в С++ он возвращает bool. По крайней мере, на моем Linux-дистрибутиве (Ubuntu) вам нужно либо объявить double trunc(double);, либо вы можете скомпилировать с помощью -std=c99 или объявить макрос уровня, чтобы получить <math.h>, чтобы объявить его.

Ответ 6

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

}

Ответ 7

#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
  }
}

Ответ 8

Как насчет этого?

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

Ответ 9

попробовать:

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;
}

Ответ 10

Ниже приведен код для тестирования 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;
     }
};

Ответ 11

Во многих вычислениях вы знаете, что ваши результаты с плавающей запятой будут иметь небольшую числовую ошибку, которая может возникнуть в результате нескольких умножений.

Так что вы действительно можете найти, так это вопрос в том, что это число в пределах 1е-5 целочисленного значения. В этом случае я думаю, что это работает лучше:

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

Ответ 12

У меня возникли аналогичные вопросы. Поскольку мне все равно нужно было обойти двойник, то, что я нахожу, работает:

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

Ответ 13

Скомпилированный пример кода:

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

 cout <<"Integer" << endl;

else

 cout <<"Flaot" << endl;

EDIT: Изменено, чтобы отобразить правильный код.