乘以1.0和int的精度浮点转换
假设条件(int)(i * 1.0f) == i
对于任何整数i
是否为真是安全的?
没有。
如果i
足够大,那么int(float(i)) != i
(假设float是IEEE-754单精度, i = 0x1000001
就足够了),那么这是错误的,因为乘以1.0f
强制转换为float
,即使后面的乘法没有改变值。
但是,如果i
是一个32位整数和double
是IEEE-754双,那么这是真的, int(i*1.0) == i
。
为了完全清楚,乘以1.0f
是确切的。 这是从int
到float
的转换,可能不是。
不, IEEE-754浮点数在整数精度的代价下具有比整数更大的dynamic范围。
看例如这个小片段的输出:
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也受到同样的问题。
-
大多数编译器有优化选项,可能会影响如何处理这种转换,忽略标准的某些限制。 在这种情况下,如果编译器将转换优化为
float
和back,(int)((float)x * 1.0f) == x
可能总是为true
。
不,行为是实现定义的,因为C和C ++不需要IEEE-754,尽pipe这是迄今为止最常见的表示。
为了确保使用IEEE-754:
- 在C中,使用
#ifdef __STDC_IEC_559__
- 在C ++中,使用
std::numeric_limits<float>::is_iec559
常量
不,这是所有的整数,因为types铸造是绝对错误的。 检查代码。
#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位整数