C 浮点表示的问题
我知道浮点数和int的位表示是不同的,但不管我存储什么值,答案总是0.000000。它不应该是取决于浮点表示的其他值吗?您的代码有未定义的行为——但只要类型C 浮点表示的问题,c,casting,floating-point,C,Casting,Floating Point,我知道浮点数和int的位表示是不同的,但不管我存储什么值,答案总是0.000000。它不应该是取决于浮点表示的其他值吗?您的代码有未定义的行为——但只要类型int和float的大小和对齐方式兼容,它的行为很可能与您期望的一样 使用“%f”格式打印*p,会丢失大量信息 试试这个: int x=25,i; float *p=(float *)&x; printf("%f\n",*p); int值25的大部分高阶位都有零。这些位可能与float类型的指数字段位于同一位置,从而导致数值非常小
int
和float
的大小和对齐方式兼容,它的行为很可能与您期望的一样
使用“%f”格式打印*p
,会丢失大量信息
试试这个:
int x=25,i;
float *p=(float *)&x;
printf("%f\n",*p);
int
值25
的大部分高阶位都有零。这些位可能与float
类型的指数字段位于同一位置,从而导致数值非常小
有关详细信息,请查阅IEEE浮点表示法。字节顺序将是一个问题。(除非有很好的理由,否则不要在实际代码中执行此类操作。)
正如rici在一篇评论中所建议的,了解浮点表示的更好方法是从浮点值开始,将其转换为大小相同的无符号整数,并以十六进制显示整数值。例如:
3.50325e-44
#包括
#包括
#包括
无效显示(浮动f){
无符号整数表示;
memcpy(代表和f、代表的大小);
printf(“%g-->0x%08x\n”,f,rep);
}
内部主(空){
if(sizeof(float)!=sizeof(unsigned int)){
fprintf(stderr,“大小不匹配\n”);
退出(退出失败);
}
显示(0.0);
show(1.0);
表演(1.0/3.0);
显示(-12.34e5);
返回0;
}
您的代码有未定义的行为——但只要类型int
和float
的大小和对齐方式兼容,它的行为很可能与您预期的一样
使用“%f”格式打印*p
,会丢失大量信息
试试这个:
int x=25,i;
float *p=(float *)&x;
printf("%f\n",*p);
int
值25
的大部分高阶位都有零。这些位可能与float
类型的指数字段位于同一位置,从而导致数值非常小
有关详细信息,请查阅IEEE浮点表示法。字节顺序将是一个问题。(除非有很好的理由,否则不要在实际代码中执行此类操作。)
正如rici在一篇评论中所建议的,了解浮点表示的更好方法是从浮点值开始,将其转换为大小相同的无符号整数,并以十六进制显示整数值。例如:
3.50325e-44
#包括
#包括
#包括
无效显示(浮动f){
无符号整数表示;
memcpy(代表和f、代表的大小);
printf(“%g-->0x%08x\n”,f,rep);
}
内部主(空){
if(sizeof(float)!=sizeof(unsigned int)){
fprintf(stderr,“大小不匹配\n”);
退出(退出失败);
}
显示(0.0);
show(1.0);
表演(1.0/3.0);
显示(-12.34e5);
返回0;
}
在本次讨论中,我们假设int
和float
都是32位宽。我们还将假设IEEE-754浮动
浮点值表示为sign*βexp*signfic和。对于32位二进制浮点,β
为2
,指数exp
范围为-126
至127
,有效位为规范化二进制分数,因此在基点之前有一个前导非零位。例如,25
的二进制整数表示为
110012
而25.0
的二进制浮点表示形式为:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void show(float f) {
unsigned int rep;
memcpy(&rep, &f, sizeof rep);
printf("%g --> 0x%08x\n", f, rep);
}
int main(void) {
if (sizeof (float) != sizeof (unsigned int)) {
fprintf(stderr, "Size mismatch\n");
exit(EXIT_FAILURE);
}
show(0.0);
show(1.0);
show(1.0/3.0);
show(-12.34e5);
return 0;
}
其中,s
表示符号位,e
表示指数位,f
表示有效位(分数)位。指数使用“超额127”符号进行编码,这意味着指数值127
(0111112
)表示0
,而1
(0000000 12
)表示-126
,254
(1111111 02
)表示127
。有效位的前导位未显式存储,因此25.0
将被编码为
s eeeeeeee fffffffffffffffffffffff
但是,将32位整数值25
的位模式映射到32位浮点格式时会发生什么情况?最后,我们得出以下结论:
0 10000011 10010000000000000000000 // exponent 131-127 = 4
事实证明,在IEEE-754浮点运算中,保留了指数值000000002
,用于表示0.0
和次正常(或非正常)数。次正常数是接近0
的数字,不能表示为12exp
,因为指数必须小于我们可以用8位编码的值。这些数字被解释为0.?*2-126个
,根据需要多个前导的0
s
在本例中,它加起来等于0.000000000000110012*2-126
,这就给出了3.50325*10-44
您必须将大的整数值(超过224
)映射到小数点后的一组小数位,才能看到除0以外的任何内容。而且,正如基思所说,这都是未定义的行为 在本次讨论中,我们假设int
和float
都是32位宽。我们还将假设IEEE-754浮动
浮点值表示为sign*βexp*signfic和。对于32位二进制浮点,β
为2
,指数exp
范围为-126
至127
,有效位为规范化二进制分数,因此在基点之前有一个前导非零位。例如,25
的二进制整数表示为
110012
而25.0
的二进制浮点表示形式为:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void show(float f) {
unsigned int rep;
memcpy(&rep, &f, sizeof rep);
printf("%g --> 0x%08x\n", f, rep);
}
int main(void) {
if (sizeof (float) != sizeof (unsigned int)) {
fprintf(stderr, "Size mismatch\n");
exit(EXIT_FAILURE);
}
show(0.0);
show(1.0);
show(1.0/3.0);
show(-12.34e5);
return 0;
}
其中,s
表示符号位,e