检查float是否为整数

时间:2011-04-26 22:00:05

标签: c floating-point int

如何检查float变量是否包含整数值?到目前为止,我一直在使用:

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

但我想知道是否有更好的解决方案,或者这个解决方案是否存在任何(或许多)缺点。

8 个答案:

答案 0 :(得分:66)

除了已经给出的优秀答案外,您还可以使用ceilf(f) == ffloorf(f) == f。如果true是整数,则两个表达式都返回f。对于NaNs(NaNs always compare unequal)和false,它们也返回true以获得±无穷大,并且没有溢出用于保存截断结果的整数类型的问题,因为{{1 } / floorf()返回ceilf() s。

答案 1 :(得分:16)

请记住,此处的大多数技术都是有效的,假设由于先前计算而导致的舍入误差不是一个因素。例如。你可以使用roundf,如下所示:

float z = 1.0f;

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

这个和其他类似技术(例如ceilf,强制转换为long等)的问题在于,虽然它们对整数常量很有效,但如果数字是计算结果受浮点舍入误差影响。例如:

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还是其他什么,都受此限制。在执行复杂或易于舍入的计算的应用程序中,通常您要做的是为构成“整数”的内容定义一些“容差”值(这通常用于浮点相等比较)。我们经常将此容差称为 epsilon 。例如,假设我们原谅计算机最多+/- 0.00001舍入误差。然后,如果我们正在测试z,我们可以选择0.00100的epsil并执行:

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

选择适合您的应用的公差值(是的,有时零容差是合适的)。有关详细信息,请查看comparing floating-point numbers上的这篇文章。

答案 2 :(得分:8)

stdlib float modf(float x,float * ipart)分为两部分,检查返回值(小数部分)== 0.

答案 3 :(得分:7)

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

不要忘记math.hlibm

答案 4 :(得分:4)

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

答案 5 :(得分:0)

我不是100%肯定,但是当你把f转换为int,并从f中减去它时,我相信它会被抛回到浮点数。在这种情况下,这可能无关紧要,但如果你因为某种原因期望它成为一个int,它可能会出现问题。

我不知道这本身是否是更好的解决方案,但您可以使用模数数字,例如: float f = 4.5886; bool isInt; isInt = (f % 1.0 != 0) ? false : true; 根据你的编译器,你可能需要或不需要.0之后,再次整个隐式转换事件发挥作用。在这段代码中,如果小数点的右边全为零,则bool isInt应为true,否则为false。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

这涉及计算四舍五入。您可以根据需要设置epsilon:

bool IsInteger(float value)
{
    return fabs(ceilf(value) - value) < EPSILON;
}