Проверка, является ли float целым числом
Как проверить, содержит ли переменная float
целочисленное значение? До сих пор я использовал:
float f = 4.5886;
if (f-(int)f == 0)
printf("yes\n");
else printf("no\n");
Но мне интересно, есть ли лучшее решение, или если у этого есть какие-то (или многие) недостатки.
Ответы
Ответ 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/