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

Проверка, является ли float целым числом

Как проверить, содержит ли переменная float целочисленное значение? До сих пор я использовал:

float f = 4.5886;
if (f-(int)f == 0)
     printf("yes\n");
else printf("no\n");

Но мне интересно, есть ли лучшее решение, или если у этого есть какие-то (или многие) недостатки.

4b9b3361

Ответ 1

Помимо тонких ответов, которые уже заданы, вы также можете использовать ceilf(f) == f или floorf(f) == f. Оба выражения возвращают true, если f - целое число. Они также возвращают false для NaNs (NaN всегда сравнивают неравные) и true для ± бесконечности и не имеют проблемы с переполнением целочисленного типа, используемого для удерживайте усеченный результат, потому что floorf()/ceilf() возвращает float s.

Ответ 2

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

float z = 1.0f;

if (roundf(z) == z) {
    printf("integer\n");
} else {
    printf("fraction\n");
}

Проблема с этим и другими подобными методами (такими как ceilf, отбрасывание на long и т.д.) ceilf в том, что, хотя они отлично работают для констант целого числа, они будут терпеть неудачу, если это число является результатом вычисления, ошибка округления округления. Например:

float z = powf(powf(3.0f, 0.05f), 20.0f);

if (roundf(z) == z) {
    printf("integer\n");
} else {
    printf("fraction\n");
}

Печатает "фракцию", хотя (3 1/20) 20 должно равняться 3, потому что фактический результат расчета оказался 2,9999992847442626953125.

Любой подобный метод, будь то fmodf или что-то еще, подчиняется этому. В приложениях, которые выполняют сложные или округлые вычисления, обычно то, что вы хотите сделать, - это определение некоторого значения "толерантности" для того, что составляет "целое число" (это относится к общим сравнениям с плавающей запятой в целом). Мы часто называем этот допуск эпсилон. Например, скажем, что мы пропустим компьютер до + / - 0,00001 ошибки округления. Тогда, если мы тестируем z, мы можем выбрать epsilon 0,00001 и сделать:

if (fabsf(roundf(z) - z) <= 0.00001f) {
    printf("integer\n");
} else {
    printf("fraction\n");
}

Вы действительно не хотите использовать ceilf здесь, потому что например ceilf(1.0000001) равен 2 не 1, а ceilf(-1.99999999) является -1 не -2.

Вы можете использовать rintf вместо roundf если хотите.

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

Ответ 3

stdlib float modf (float x, float * ipart) делится на две части, проверьте, является ли возвращаемое значение (дробная часть) == 0.

Ответ 4

if (fmod(f, 1) == 0.0) {
  ...
}

Не забывайте math.h и libm.

Ответ 5

if (f <= LONG_MIN || f >= LONG_MAX || f == (long)f) /* it an integer */

Ответ 6

Я не уверен на 100%, но когда вы накладываете f на int и вычитаете его из f, я считаю, что он возвращается к float. В этом случае это, вероятно, не имеет значения, но может возникнуть проблема в строке, если вы ожидаете, что это будет по какой-то причине.

Я не знаю, является ли это лучшим решением как таковым, но вместо этого вы можете использовать математику по модулю, например: float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true; в зависимости от вашего компилятора вы можете или не нуждаетесь в .0 после 1, снова появляется вся неявная броска. В этом коде bool isInt должен быть истинным, если правая часть десятичной точки равна нулю, а false в противном случае.

Ответ 7

#define twop22 (0x1.0p+22)
#define ABS(x) (fabs(x))
#define isFloatInteger(x) ((ABS(x) >= twop22) || (((ABS(x) + twop22) - twop22) == ABS(x)))

Ответ 8

Хорошо, что я недавно столкнулся с этой проблемой и, на удивление, нашел для вас любые решения в Интернете. Итак, вот мое решение. Например, если значение равно 3.00, и нам нужно только 3, тогда нам нужно проверить, следует ли после "." есть нули или нет. Если все это можно преобразовать в int или иначе, оно останется плавающим. Поэтому включите эту функцию

int isInt(float val)
{
    int i = (int) val;
    if( i != val)
      return 0;  // its not an integer
    else
      return 1;  // is an integer
}
int main()
{
  float i = 3.9;   // not this is an example.
  if(isInt())
  printf("%d", i);
  else
  printf("%f", i);
  return 0;
}

Надеюсь, что это поможет!

http://anandkhinvasara.com/check-whether-number-integer-float-c/