浮点表示问题

时间:2015-07-09 18:11:25

标签: c casting floating-point

int x=25,i; 
float *p=(float *)&x;
printf("%f\n",*p);

我理解浮点数和int的位表示是不同的,但无论我存储什么值,答案总是0.000000。取决于浮点表示,它不应该是其他值吗?

2 个答案:

答案 0 :(得分:6)

您的代码具有未定义的行为 - 但只要类型intfloat的大小和对齐方式兼容,它很可能会按预期运行。

使用“%f”格式打印*p,您将丢失大量信息。

试试这个:

#include <stdio.h>
int main(void) {
        int x = 25; 
        float *p = (float*)&x;
        printf("%g\n", *p);
        return 0;
}

在我的系统上(可能在你的系统上),它会打印:

3.50325e-44

int25在其大多数高位中都为零。这些位可能与类型float的指数字段位于同一位置 - 导致数字非常小。

查找IEEE浮点表示以获取更多信息。字节顺序将是一个问题。 (除非你有非常充分的理由,否则不要在实际代码中执行此类操作。)

正如rici在评论中所建议的,学习浮点表示的更好方法是从浮点值开始,将其转换为相同大小的无符号整数,并以十六进制显示整数值。例如:

#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;
}

答案 1 :(得分:0)

出于本讨论的目的,我们假设intfloat都是32位宽。我们还将承担IEEE-754浮标。

浮点值表示为sign * βexp * signficand。对于32位二进制浮点数,β2,指数 exp 的范围为-126127,而< em> significand 是规范化二进制分数,因此在小数点之前存在单个前导非零位。例如,25的二进制整数表示是

110012

25.0的二进制浮点表示形式为:

1.10012 * 24 // normalized 

32位浮点数的IEEE-754编码

s eeeeeeee fffffffffffffffffffffff

其中s表示符号位,e表示指数位,f表示有效位(分数)位。使用&#34;超过127&#34;编码指数。表示法,表示指数值127011111112)表示0,而1000000012)表示-126和{{1} }(254)代表111111102。未显式存储有效位数的前导位,因此127将被编码为

25.0

但是,将32位整数0 10000011 10010000000000000000000 // exponent 131-127 = 4 位模式映射到32位浮点格式时会发生什么?我们结束了以下几点:

25

事实证明,在IEEE-754浮点数中,指数值0 00000000 00000000000000000011001 被保留用于表示000000002次正常(或非正规)数字。次正规数是接近0.0的数字,不能表示为0,因为指数必须小于我们可以用8位编码的数量。这些数字被解释为1.??? * 2exp,并根据需要提供尽可能多的前导0.??? * 2-126

在这种情况下,它最多为0,这为我们提供了0.000000000000000000110012 * 2-126

您必须映射大整数值(超过3.50325 * 10-44)以查看除0之外的任何内容到一堆小数位。而且,就像基思所说,无论如何,这都是未定义的行为。