假设条件(int)(i * 1.0f) == i
对于任何整数i
都为真,是否安全?
答案 0 :(得分:70)
没有
如果i
足够大int(float(i)) != i
(假设浮点数是IEEE-754单精度,i = 0x1000001
足以表示这一点)那么这是假的,因为乘以{{1}强制转换为1.0f
,即使后续乘法没有改变,也会改变值。
但是,如果float
是32位整数且i
是IEEE-754 double,则 为真double
。
为了完全清楚,乘以int(i*1.0) == i
的确是。这是从1.0f
到int
的转换,可能不是。
答案 1 :(得分:14)
不,IEEE-754浮点数的动态范围大于整数,相同位宽的整数精度成本。
例如,请参阅此小片段的输出:
int main() {
int x = 43046721;
float y = x;
printf("%d\n", x);
printf("%f\n", y);
}
43046721
无法在32位float
数字中可用的24位精度中正确表示,因此输出就是这些行:
43046721
43046720.000000
事实上,我希望在转换为32位float
数字时,任何高于16,777,216的奇数都会出现同样的问题。
一些兴趣点:
这与隐式的int-to-float转换有关,而不是与乘法本身有关。
这不是C的任何独特之处 - 例如Java也存在完全相同的问题。
大多数编译器都有优化选项,可能会影响这些转换的处理方式,忽略了标准的某些限制。在这种情况下,如果编译器将转换优化为(int)((float)x * 1.0f) == x
并返回,则true
可能始终为float
。
答案 2 :(得分:1)
不,行为是实现定义的,因为C和C ++不需要IEEE-754,即使这是迄今为止最常见的表示。
确保使用IEEE-754:
#ifdef __STDC_IEC_559__
std::numeric_limits<float>::is_iec559
常量答案 3 :(得分:-5)
由于类型转换,所有整数都不是绝对错误的。检查代码。
#include <stdio.h>
int main()
{
int i = 0;
for (; i < 2147483647; ++i) {
if ((int)(i * 1.0f) != i) {
printf("not equal\n");
break;
}
}
printf("out of the loop\n");
getchar();
return 0;
}
此代码假定您采用32位整数