如何检查float
变量是否包含整数值?到目前为止,我一直在使用:
float f = 4.5886;
if (f-(int)f == 0)
printf("yes\n");
else printf("no\n");
但是我想知道是否有更好的解决方案,或者这个解决方案是否有(或很多)缺点。
如何检查float
变量是否包含整数值?到目前为止,我一直在使用:
float f = 4.5886;
if (f-(int)f == 0)
printf("yes\n");
else printf("no\n");
但是我想知道是否有更好的解决方案,或者这个解决方案是否有(或很多)缺点。
float
,大概是因为要对其进行浮点运算。然后,您的问题就变成了:该变量的值在特定于领域的方式中是有点蓬松的,并且取决于您对算术的认真程度,因此它的值是蓬松积分的吗?要有意义地回答该问题,您需要考虑特定于域的蓬松度。或者,换一种说法:在哪种情况下,正确的方法是不以int
适当的大小存储您的值?
Answers:
除了已经给出的好答案之外,您还可以使用ceilf(f) == f
或floorf(f) == f
。true
如果f
是整数,则两个表达式均返回。它们还会返回false
NaN(NaN总是比较unqual)和true
±无限,并且不会溢出用于保存截断结果的整数类型,因为floorf()
/ ceilf()
return float
s。
f
,是的,但是这样做是为了检查它是否是整数。
f
,舍入运算的结果是怎样的,谢谢,我已经编辑了答案以使其更清楚。
ceilf
并且floorf
都在至少某些archs(主要是X86)由于需要改变不必要的昂贵的操作和恢复舍入模式。更快的测试是rintf(f)==f
。使用-fno-math-errno
,GCC将编译rintf
为单个内联指令。
nearbyintf
没有异常或标记也可以这样做?
请记住,这里的大多数技术都是有效的,前提是由于先前的计算导致的舍入误差不是一个因素。例如,您可以使用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
无论是哪种方法,都应受此约束。在执行复杂或四舍五入计算的应用程序中,通常要做的是为构成“整数”的值定义一些“公差”值(通常用于浮点相等比较)。我们常把这种公差称为ε。例如,假设我们将对最大舍入误差为+/- 0.00001的计算机进行原谅。然后,如果我们正在测试z
,我们可以选择0.00001的epsilon并执行:
if (fabsf(roundf(z) - z) <= 0.00001f) {
printf("integer\n");
} else {
printf("fraction\n");
}
您实际上并不想在ceilf
这里使用,因为egceilf(1.0000001)
是2而不是1,并且ceilf(-1.99999999)
是-1而不是-2。
如果愿意,可以使用rintf
代替roundf
。
选择适合您的应用的公差值(是的,有时零公差是合适的)。有关更多信息,请查看有关比较浮点数的本文。
stdlib float modf(float x,float * ipart)分为两部分,检查返回值(小数部分)== 0。
if (f <= LONG_MIN || f >= LONG_MAX || f == (long)f) /* it's an integer */
sizeof(f) > sizeof(long)
这可能不成立。
double
。
double
我会使用long long
和LLONG_MAX
/ LLONG_MIN
。
(long)f
如果该值不能表示为,则调用未定义的行为long
。因此,为了安全起见,您必须先进行比较。
float
受到限制,以使得最接近该数字的可表示值是-109999998686059298816,它也是一个整数。由于float
具有24位有效数,因此大小至少2 ^ 24的任何值在小数点之后都没有有效位。C要求long
至少为32位,因此值大于LONG_MAX
或小于LONG_MIN
该范围之外的值。
我不确定100%,但是当您将f转换为int并从f中减去时,我相信它会转换为浮点数。在这种情况下这可能无关紧要,但是如果您出于某种原因希望它是一个int,则可能会带来一些问题。
我不知道它本身是否是一个更好的解决方案,但是例如,您可以使用模数数学:
float f = 4.5886;
bool isInt;
isInt = (f % 1.0 != 0) ? false : true;
根据您的编译器,您可能需要或不需要1.之后的.0,这又使整个隐式强制转换起作用。在此代码中,如果小数点右边的全为零,则bool isInt应该为true,否则为false。
%
操作仅适用于整数。您对int被强制转换回浮点数是正确的。