x
是int
。
我认为x==(int)(float)x
始终是真的,但当x
为TMax
时,该书说它是假的。
我在x=TMax
时检查过它,它仍然是真的。这本书错了吗?
答案 0 :(得分:2)
float
具有IEEE-754浮点格式的24位精度。只要整数值具有更高的精度,就会失去精度。在具有32位int
s的系统上尝试相同的操作,您将看到差异。
例如,点击
#include <stdio.h>
int main()
{
unsigned int x = 4000000003U;
float y = x;
printf ("%u %.20g %.20g %u\n", x, (float)x, y, (unsigned int)(float)x);
}
将这个大数字转换为浮点数。这个浮点数不能保持整数,所以它接近它。
转换回int
后,您会获得不同的价值。
至少,你应该得到一个,但我不能在我的系统上重现这个:上面的程序输出
4000000003 4000000003 4000000000 4000000003
虽然我预计第二个数字等于第三个......
但是,如果我将代码更改为64位整数:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main()
{
uint64_t x = 400000000000000003U;
double y = x;
printf ("%" PRIu64 " %.20g %.20g %" PRIu64 "\n", x, (double)x, y,
(uint64_t)(double)x);
}
它将按预期工作:64位甚至超过double
可以容纳(这将是53位),因此它可以按原样工作。
答案 1 :(得分:1)
不一定是这样,因为随着您增加值的大小,浮点会失去精度。
答案 2 :(得分:1)
假设使用IEEE-754,单精度float
只能在2 24 内准确表示整数,但int
在现代计算机中通常为32位,范围之外的整数可能不会被(int)(float)x
如果使用double
而不是float
,则x == (int)(double)x
对于所有32位整数都为真,因为double
可以表示2 53内的整数
答案 3 :(得分:0)
tczf,你必须阅读CSAPP这本书,我想你可以看一下练习题2.49,这是在144页。带有n位分数的浮点格式不能代表整数它大于2 ^(n + 1)-1,因为它会失去精度。
因此,IEEE 754单精度浮点格式具有23位分数,而“int”类型具有32位,因此如果整数大于2 ^ 24-1,则float类型不能完全代表它。但是双浮点格式可以,因为它有52位分数。
答案 4 :(得分:0)
@ FatSheep的答案有误。
具有n位小数的浮点格式不能表示大于2 ^(n + 1)-1的整数,因为它将失去精度。
不是2^(n+1)-1
,正确的是which larger than or equal to 2^(n+1) + 1
。
n + 1
表示归一化值隐含前导1,并且有效位数等于M = 1 + f
,f代表分数。
该代码将为您提供帮助。
#include<stdio.h>
#include<limits.h>
int main(){
for(int i =0; i < INT_MAX; i++){
int x = i;
int y = (int)(float)x;//when x >= 2^(n + 1) + 1, x != y
if(x != y){
printf("%d,%d\n",x,y);
break;
}
}
return 0;
}