为什么以下代码的行为与在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,对吗?
答案 0 :(得分:3)
要表示的值为2147483647.可以用这种方式表示的下两个值是2147483520和2147483648.
由于后者更接近无法代表的“理想之一”,因此会使用它:在浮点数中,值会四舍五入,而不会被截断。
答案 1 :(得分:1)
The standard is available here。您可能不得不购买它,因为IEEE(以及其他类似组织)主要通过销售标准来赚钱,以支付他们组装,游说接受和提高标准质量的成本。
这些位只表示有人指定它们
“当我用一句话时,”Humpty Dumpty用一种轻蔑的语气说道,“它 意味着我选择它的意思 - 既不多也不少。“” 问题是,“爱丽丝说,”你是否可以说出这么多的话 不同的事情。“”问题是,“Humpty Dumpty说,”这是 掌握 - 这就是全部。“(通过镜子,第6章)
在这种情况下,IEEE决定了这些位的含义,以及printf标志%f打印出正确的相应人类表示的原因是由于该标志也遵循相同的标准。
有时您可以设法将位转换为另一种数据类型(如int)并打印出这些位的“其他”表示。 C会捕获很多正常的号码促销,但你可以混淆它,通常是在将错误类型的指针分配给正确的地址(并解除引用它们)的帮助下。
请注意,当您手动进行数学运算时,实际硬件并不能保证完全按照您的方式进行数学运算。使用整数数学,表示中的准确度要高得多,但对于浮点数学,如何舍入数字会使输出产生很大的差异。这甚至没有提到有时被烧入系统的浮点错误(幸好不经常)。
答案 2 :(得分:1)
浮点格式通常采用“标准化格式”,其中尾数的最高位始终为1.因为它始终为1,所以您不需要用一点来存储它。因此,在解码这样的数字表示时,您需要在顶部添加1。
答案 3 :(得分: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