C 浮点表示的问题

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的位表示是不同的,但不管我存储什么值,答案总是0.000000。它不应该是取决于浮点表示的其他值吗?

您的代码有未定义的行为——但只要类型
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