IEEE 754:它是如何运作的?

4
以下代码在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,对吗?
4个回答

3
要表示的值将是2147483647。可以用这种方式表示的下两个值分别是2147483520和2147483648。
由于后者更接近无法表示的“理想值1”,因此它被使用:在浮点数中,值会被四舍五入,而不是截断。

1
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

1

标准在此处可用。您可能需要购买它,因为IEEE(以及其他类似组织)主要通过销售标准来赚钱,以抵消他们在组装、游说接受和提高标准质量方面的成本。

位只意味着某人指定它们的含义

“当我使用一个词时,”亨普蒂·韦尔德(Humpty Dumpty)用相当轻蔑的语气说,“它的意思就是我选择的意思——既不多也不少。” “问题是,”爱丽丝说,“你能不能让单词有这么多不同的意思。” “问题是,”亨普蒂·韦尔德说,“谁将是主人——这就是全部。”(《镜中奇遇记》第6章)

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

有时候你可以将二进制位转换成其他的数据类型(比如整型)并打印出这些二进制位的“另一种”表示。C语言会捕捉到许多普通数字提升,但是你可以通过在正确的地址上分配错误类型的指针(并对它们进行解引用),来混淆它。

请注意,当你手动计算时,实际的硬件不能保证按照你所想象的精确进行计算。使用整数Math表示更准确,但浮点数Math中,舍入的方式对输出结果有很大影响。更不用说有时候系统中还会出现浮点数误差问题(幸好不太常见)。


1

浮点数格式通常处于“规范化形式”,其中尾数的最高有效位始终为1。由于它始终为1,因此您不需要使用一个位来存储它。因此,在解码这种数字表示时,您需要在顶部添加回1。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接