从内存中提取double的字节值

3
我正在尝试从计算机内存中提取double类型的字节值。这样做是为了精度,因为最终呈现给用户的值经过了一些舍入。

理想情况下,我希望能够从数字(IEEE 754标准)中提取符号、指数和尾数。

据我所知,将其转换为无符号字符是可行的方法。我有以下代码片段(从其他地方借来的),但我不信任结果——没有任何整数值的字节输出:

double d = 2;
unsigned char *p = (unsigned char*)&d;

有人能指导我如何准确地提取双精度浮点数的字节表示吗?或者就如何进行提取给出任何建议或意见?


3
你是否知道标准库中的frexp()函数? - Oliver Charlesworth
整数值?它是一个“double”。你是如何安排输出的呢?那段代码只创建了一个“double”和一个指针。 - Lightness Races in Orbit
1
另外,我不理解你的前提。提取原始位如何帮助你提高准确性? - Oliver Charlesworth
你说的“任何整数值没有字节输出”是什么意思?展示一下你的输出。另外,为什么使用C风格的转换而不是C++风格的? - Grizzly
1
简要说明(这是我的理解),浮点数二进制值有时无法准确地表示数字。因此,可能会涉及一些潜在的损失/舍入。如果我执行需要精度和使用多个会话/计算机的模拟或一些数字计算,则如果我将间歇结果保存为ASCII值,有可能,当我使用这些结果开始新会话时,我会有一个误差,随着时间的推移,它会变得越来越大(即使实际上它很小)。 - nf313743
显示剩余5条评论
2个回答

5

你做对了。现在你可以将p视为一个unsigned char[sizeof(double)]的数组。

例如:

for (int i = 0; i != sizeof(double); ++i)  printf("%02X ", p[i]);

对于 d = 0.125,这将打印出 00 00 00 00 00 00 C0 3F。反转字节序并分解成部分,得到:

00111111 11000000 0 0 0 0 0 0
   3F       C0    0 0 0 0 0 0

0   01111111100   0...<52 times>...0
S     Exponent         Mantissa
+     1023 - 3           1.0

指数域的值为1020,通过校正偏差1023后,对数为-3,而底数为1.0,在包含隐式前导1之后。 因此,值为2-3 = 1/8。

3

如果您只关心准确性,请使用 printf("%a\n", d);

它显示的信息与查看二进制表示相同,但以几乎可读的格式显示。在这里(即对于d=2;),它显示为0x1p+1。在0x后面的数字是尾数,在1和2之间标准化,并且用十六进制表示。在p后面的数字是指数。它以十进制显示,但表示的是2的幂。


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