【问题标题】:IEEE 754: How exactly does it work?IEEE 754:它究竟是如何工作的?
【发布时间】:2011-08-10 04:20:33
【问题描述】:

为什么以下代码的行为与在 C 中的行为相同?

float x = 2147483647; //2^31
printf("%f\n", x); //Outputs 2147483648

这是我的思考过程:

2147483647 =   0      1001 1101      1111 1111 1111 1111 1111 111

   (0.11111111111111111111111)base2 = (1-(0.5)^23)base10
=> (1.11111111111111111111111)base2 = (1 + 1-(0.5)^23)base10 = (1.99999988)base10

因此,要将 IEEE 754 表示法转换回十进制:1.99999988 * 2^30 = 2147483520

所以从技术上讲,C 程序一定打印出了 2147483520,对吧?

【问题讨论】:

    标签: c floating-point floating-accuracy ieee-754


    【解决方案1】:

    要表示的值是 2147483647。接下来可以用这种方式表示的两个值是 2147483520 和 2147483648。

    由于后者更接近无法表示的“理想值”,因此它被使用:在浮点数中,值被四舍五入,而不是截断。

    【讨论】:

      【解决方案2】:

      The standard is available here。您可能必须购买它,因为 IEEE(和其他类似的组织)主要通过出售标准来赚钱,以支付他们在组装、游说接受和提高标准质量方面的成本。

      这些位仅表示某人指定它们的含义

      “当我使用一个词时,”矮胖子用相当轻蔑的语气说,“它 意思就是我选择的意思——不多也不少。” “The 问题是,”爱丽丝说,“你能不能把词说成这么多 不同的东西。” “问题是,”矮胖子说,“这是为了 成为大师——仅此而已。”(通过镜子,第 6 章)

      在这种情况下,IEEE 已经决定了这些位的含义,而 printf 标志 %f 打印出正确的对应人类表示的原因是由于该标志也遵循相同的标准。

      有时您可以设法将这些位转换为另一种数据类型(如 int)并打印出这些位的“其他”表示。 C 会捕获很多正常的数字提升,但您可能会混淆它,通常是在将错误类型的指针分配给正确地址(并取消引用它们)的帮助下。

      请注意,当您手动进行数学运算时,实际的硬件并不能保证完全按照您的意愿进行数学运算。使用整数数学,表示的准确性要高得多,但使用浮点数学,如何对数字进行四舍五入会对输出产生很大影响。这甚至没有提到有时会被烧入系统的浮点错误(幸好不经常)。

      【讨论】:

        【解决方案3】:

        浮点格式通常采用“标准化形式”,其中尾数的最高有效位始终为 1。由于它始终为 1,因此您无需用尽一点来存储它。所以在解码这样一个数字表示时,你需要在顶部加回 1。

        【讨论】:

          【解决方案4】:
          2147483647 = 2^31 - 1 = +1 * 2^30 * 1.1111 1111 1111 1111 1111 1111 1111 11
          

          以 IEEE 754-1985 单精度格式编码此数字时,有效数字会正确舍入。对于舍入模式四舍五入到最接近的偶数(默认舍入模式),这意味着它会向上舍入。

          四舍五入前:

          exponent = 30, significand = 1.1111 1111 1111 1111 1111 1111 1111 11
          

          将有效位四舍五入到小数点后23位:

          exponent = 30, significand = 10.0000 0000 0000 0000 0000 000
          

          标准化后:

          exponent = 31, significand = 1.0
          

          以单精度格式编码:

          1 | 10011110 | 00000000000000000000000
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-05-16
            • 2014-04-30
            • 1970-01-01
            • 2020-06-04
            • 2016-02-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-26
            相关资源
            最近更新 更多