Is it safe to assume that the condition (int)(i * 1.0f) == i
is true for any integer i
?
4 回答
不。
如果i
足够大int(float(i)) != i
(假设 float 是 IEEE-754 单精度,i = 0x1000001
足以证明这一点)那么这是错误的,因为乘以1.0f
强制转换为float
,即使随后的乘法不会改变值。
但是,如果i
是 32 位整数并且是IEEE-754 双精度,double
那么.int(i*1.0) == i
为了完全清楚,乘法1.0f
是准确的。可能不是从int
到的转换。float
不,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
事实上,我希望任何高于 16,777,216 的奇数在转换为 32 位float
数字时都会出现同样的问题。
几个兴趣点:
这与隐式 int-to-float 转换有关,而不是与乘法本身有关。
这绝不是 C 独有的——例如 Java 也遇到完全相同的问题。
大多数编译器都有优化选项,通过忽略标准的某些限制,可能会影响处理此类转换的方式。在这种情况下,如果编译器优化了来回转换,则
(int)((float)x * 1.0f) == x
可能总是如此。true
float
不,行为是实现定义的,因为 C 和 C++ 不需要 IEEE-754,尽管这是迄今为止最常见的表示。
为确保使用 IEEE-754:
- 在 C 中,使用
#ifdef __STDC_IEC_559__
- 在 C++ 中,使用
std::numeric_limits<float>::is_iec559
常量
不,由于类型转换,所有整数都是绝对错误的。检查代码。
#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 位整数