Li.*_*ang 1 floating-point visual-c++
从浮点数的计算机表示中我学到了计算机的浮点表示。
\n根据教程,对于32位浮点数,可以存储的最小正归一化数\n是2^(-126)\xef\xbc\x8c,最大归一化数是(2-2^(-23)) *2^(127)\xe2\x89\x88 2^(128)。然而,精度受到 23 位有效数的限制。
在我看来,32位浮点数可以表示2^60而不会出现任何错误,因为:
\n\n用指数和尾数的隐藏位(1)来表示2^60就完全足够了。
\n\n我的测试代码如下(VS2013 + win10):
\n\n#include <iostream>\n#include <math.h>\n#include <bitset>\n\nusing namespace std;\n\nint main()\n{\n union\n {\n float input; // assumes sizeof(float) == sizeof(int)\n int output;\n } data;\n\n data.input = pow(2., 60.);\n\n std::bitset<sizeof(float) * CHAR_BIT> bits(data.output);\n\n\n std::cout << "Total: " << bits << std::endl;\n\n\n cout << "Sign: " << bits[31] << endl << "Exponent: ";\n\n for (int i = 30; i > 22; i--)\n {\n cout << bits[i];\n }\n cout << endl << "Significand: ";\n\n for (int i = 22; i >= 0; i--)\n {\n cout << bits[i];\n }\n cout << endl;\n\n\n cout.precision(20);\n cout << data.input << endl;\n printf("%f", data.input);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我得到输出:
\n\n Total: 01011101100000000000000000000000\n Sign: 0\n Exponent: 10111011\n Significand: 00000000000000000000000\n 1152921504606847000\n 1152921504606847000.000000\nRun Code Online (Sandbox Code Playgroud)\n\n我打印了二进制表示形式,它是正确的。但我很困惑为什么最后三位数字为零。正确的输出应该是 1152921504606846976。
\n\n此外,我将代码更改如下:
\n\n#include <iostream>\n#include <math.h>\n#include <bitset>\n\nusing namespace std;\n\nint main()\n{\n for (int i = 1; i < 65; i++)\n {\n union\n {\n float input; // assumes sizeof(float) == sizeof(int)\n int output;\n } data;\n\n data.input = pow(2, i);\n\n std::bitset<sizeof(float) * CHAR_BIT> bits(data.output);\n\n\n cout.precision(20);\n cout << i << ": " << data.input << endl;\n //printf("%f\\n", data.input);\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n\n输出是:
\n\n1: 2\n2 : 4\n3 : 8\n ......\n55 : 36028797018963968\n56 : 72057594037927936\n57 : 144115188075855870\n58 : 288230376151711740\n59 : 576460752303423490\n60 : 1152921504606847000\n61 : 2305843009213694000\n62 : 4611686018427387900\n63 : 9223372036854775800\n64 : 18446744073709552000\nRun Code Online (Sandbox Code Playgroud)\n\n零从 2^57 开始出现。谁能告诉我为什么会发生这种情况?
\n这并不是无法正确float表示 2 60。是 Microsoft\xe2\x80\x99s 软件无法正确将 2 60转换为十进制(也就是说,故障出在格式化代码中,而不是算术中float,尽管 Microsoft\xe2\x80\x99spow之前的实现也是不准确的) )。无论涉及的实际值是多少,您使用的软件仅生成 17 位十进制数字。使用 Apple LLVM 10.0.0 (clang-1000.11.45.5) 编译的同一程序会生成:
\n55: 36028797018963968\n56: 72057594037927936\n57: 144115188075855872\n58: 288230376151711744\n59: 576460752303423488\n60: 1152921504606846976\n61: 2305843009213693952\n62: 4611686018427387904\n63: 9223372036854775808\n64: 18446744073709551616\n\n\n
Microsoft\xe2\x80\x99s 的行为是 C 标准所允许的,但当然在数学上并不好。
\n| 归档时间: |
|
| 查看次数: |
217 次 |
| 最近记录: |