【问题标题】:Issue with floating point representation浮点表示的问题
【发布时间】:2015-07-09 18:11:25
【问题描述】:
int x=25,i; 
float *p=(float *)&x;
printf("%f\n",*p);

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

【问题讨论】:

  • 你为什么不换个方向试试,看看小浮点数是如何表示的。 (和/或在维基百科做一些研究。)
  • 该值为 0.000000000000000000000000000000000000000000035,显示为 0.0000035,因为您使用了 %f 格式。您可以使用this web site 尝试其他值。
  • 我投票结束这个问题,因为它试图解释 UB。
  • 另外,它是一个多副本,最近至少被问过一次。 stackoverflow.com/questions/17898186/…

标签: c casting floating-point


【解决方案1】:

您的代码具有未定义的行为 - 但它很可能会按照您的预期运行,只要类型 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;
}

【讨论】:

    【解决方案2】:

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

    浮点值表示为<em>sign</em> * β<sup><em>exp</em></sup> * <em>signficand</em>。对于 32 位二进制浮点数,β2,指数 exp 范围从 -126127有效位 是 归一化二进制小数,这样在小数点之前有一个前导非零位。例如25的二进制整数表示为

    11001<sub>2</sub>

    25.0 的二进制浮点表示为:

    1.1001<sub>2</sub> * 2<sup>4</sup> // normalized 

    32 位浮点数的 IEEE-754 编码是

    s eeeeeeee fffffffffffffffffffffff
    

    其中s 表示符号位,e 表示指数位,f 表示有效数(小数)位。指数使用“excess 127”表示法编码,这意味着指数值127 (01111111<sub>2</sub>) 代表0,而1 (00000001<sub>2</sub>) 代表-126254 (11111110<sub>2</sub> ) 代表127。有效数字的前导位未显式存储,因此25.0 将被编码为

    0 10000011 10010000000000000000000 // exponent 131-127 = 4
    

    但是,当您将 32 位 整数25位模式 映射到 32 位浮点格式时会发生什么?我们最终得到以下结果:

    0 00000000 00000000000000000011001
    

    事实证明,在 IEEE-754 浮点数中,指数值 00000000<sub>2</sub> 保留用于表示 0.0次正规(或非正规)数字。次正规数是接近0 的数字,它不能表示为1.??? * 2<sup><em>exp</em></sup>,因为指数必须小于我们可以用8 位编码的值。这些数字被解释为0.??? * 2<sup>-126</sup>,必要时有尽可能多的前导0s。

    在这种情况下,它加起来为0.00000000000000000011001<sub>2</sub> * 2<sup>-126</sup>,即为3.50325 * 10<sup>-44</sup>

    您必须映射大整数值(超过2<sup>24</sup>)才能看到除 0 以外的任何内容到一堆小数位。而且,就像 Keith 所说,无论如何,这都是未定义的行为。

    【讨论】:

      猜你喜欢
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-07
      • 2016-08-28
      • 2016-06-04
      • 1970-01-01
      相关资源
      最近更新 更多