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

Я предпочитаю Freemarker, здесь по Скорости; imo, Freemarker, намного более простой в этом случае.

при использовании Spring, тогда можно интересоваться, Freemarker в Spring MVC.

39
задан Jacob 5 October 2009 в 18:33
поделиться

11 ответов

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

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

Не преобразовывать в int ! Число 1.0e + 300 тоже целое, как вы знаете.

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

71
ответ дан 27 November 2019 в 02:18
поделиться

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

bool double_is_int(double trouble) {
   double absolute = abs( trouble );
   return absolute == floor(absolute);
}
9
ответ дан 27 November 2019 в 02:18
поделиться

avakar был почти прав - используйте modf, но детализация была отключена.

modf возвращает дробную часть, поэтому проверка должна состоять в том, что результат modf равен 0,0.

modf принимает два аргумента, второй из которых должен быть указателем того же типа, что и первый аргумент. Передача NULL или 0 вызывает ошибку сегментации в среде выполнения g ++. Стандарт не указывает, что передача 0 безопасна; может случиться так, что он работает на машине авакара, но не делайте этого.

Вы также можете использовать fmod (a, b) , который вычисляет a по модулю 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

}
4
ответ дан 27 November 2019 в 02:18
поделиться

Как насчет

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 */
}

Есть еще одно решение с выступлением , вычитая 0,5 и беря abs () из этого и сравнивая с 0,499999999, но я полагаю, что это не будет значительным улучшением производительности.

3
ответ дан 27 November 2019 в 02:18
поделиться
int iHaveNoFraction(double d){
    return d == trunc(d);
}

Это не был бы C, если бы он не пересматривался за 40 лет ...

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

3
ответ дан 27 November 2019 в 02:18
поделиться

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

if ((d1 - (int)d1) == 0)
    // integer
2
ответ дан 27 November 2019 в 02:18
поделиться

попробуйте:

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;
}
0
ответ дан 27 November 2019 в 02:18
поделиться
#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
  }
}
0
ответ дан 27 November 2019 в 02:18
поделиться

Ниже приведен код для тестирования 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;
     }
};
0
ответ дан 27 November 2019 в 02:18
поделиться

Пример кода, который это делает:

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

 cout <<"Integer" << endl;

else

 cout <<"Flaot" << endl;

РЕДАКТИРОВАТЬ: Изменен, чтобы отразить правильный код.

-1
ответ дан 27 November 2019 в 02:18
поделиться

Предполагая, что среда совместима с c99 и IEEE-754,

(trunc(x) == x)

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

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


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

5
ответ дан 27 November 2019 в 02:18
поделиться