【发布时间】:2021-07-15 19:35:01
【问题描述】:
这是我的尝试:
#include <iostream>
union newType {
long double firstPart;
unsigned char secondPart[sizeof(firstPart)];
} lDouble;
int main() {
lDouble.firstPart = -16.5;
for (int_fast16_t i { sizeof(lDouble) - 1 }; i >= 0; --i)
std::cout << (int)lDouble.secondPart[i] << " ";
return 0;
}
输出:0 0 0 0 0 0 192 3 132 0 0 0 0 0 0 0 十六进制:0 0 0 0 0 0 c0 3 84 0 0 0 0 0 0 0
我几乎同意“c0 3 84”部分,即“1100 0000 0000 0011 1000 0100”。
-16.5 = -1.03125 * 2^4 = (-1 + (-0.5) * 2^-4) * 2^4 因此,我的小数部分的第 117 位必须为 1,在第 5 次除法之后,我将只得到“0”。 符号(-):1 指数(2^4):4 + 16383 = 16387 = 100 0000 0000 0011 分数:0000 1000 和 104 '0' 结果:1| 100 0000 0000 0011| 0000 1000 和 104 '0' 十六进制:c 0 0 3 0 8 和 26 '0' 或:c0 3 8 0 0 0 0 0 0 0 0 0 0 0 0 0我没有得到两件事:
- "c0 3 84" - 我的计算在哪里丢失了 4?我的猜测是它以某种方式存储 1(113 位)并且不应该存储。然后是 1000 0100 而不是 0000 1000(在“c0 3”之后),这正是“84”。但我们总是存储 112 位,而 1 总是隐含的。
- 为什么我的输出不是从 192 开始?为什么从0开始?我认为第一位是符号位,然后是指数(15 位)和小数(112 位)。
我已经设法表示其他数据类型(double、float、unsigned char 等)。使用 double 我采用了类似的方法并得到了预期的结果(例如 double -16.5 输出 192 48 128 0 0 0 0 0 或 c0 30 80 0 0 0 0 0)。
当然我已经测试过How to print binary representation of a long double as in computer memory?的解决方案
我的 -16.5 的值为:0 0 0 0 0 0 0 0x84 0x3 0xc0 0xe2 0x71 0xf 0x56 0 0 如果我恢复这个我得到: 0 0 56 f 71 e2 c0 3 84 0 0 0 0 0 0 0
我不明白为什么(再次)序列不是从符号位开始,那些“56 f 71 e2 c0”是什么?他们来自哪里?为什么(再次)在“8”之后有“4”?
【问题讨论】:
-
大小和二进制表示取决于您的系统。不需要 80 位或使用 IEEE-754。 cppreference "long double - 扩展精度浮点类型。不一定映射到 IEEE-754 规定的类型。通常在 x86 和 x86-64 架构上为 80 位 x87 浮点类型。”
-
我没有抱怨所需的尺寸。
sizeof(long double)给了我 16(128 位),我认为我的数组应该从最左边的位填充,仅此而已。所以我的系统使用 IEEE-754 作为双倍,而对于长双倍它使用其他东西?这很奇怪,那我会在我的Linux机器上试试。非常感谢,@jabaa。 -
@Xofrio 对于
long double,它仍然使用IEEE-754,但不是 binary128。那是binary64 extended format。另见Is long double in C++ an implementation of IEEE's binary128?、What is long double on x86-64?、Why does a long double take up only 10 bytes in a string?
标签: c++ ieee-754 long-double