3

我想了解数字(双精度)如何在 bash 中表示,以及当我在 bash 中以十六进制格式打印数字时会发生什么。

根据 IEEE 754 标准,double 应由 64 位表示:52 位(13 个十六进制数)表示有效数,11 位表示指数,1 位表示符号。

为了检查它,我编写了一个简单的 C 程序,将十六进制转换为十进制(使用 printf)。

include <stdio.h>
int main(int argc, char **argv)
{
printf("hex read = %40.24a\n", 0x1.000010C6F7A0B5E1Fp+0);
}

用 gcc 4.2.1 编译,我得到

hex read =          0x1.000010c6f7a0b00000000000p+0

从这个结果我得出结论,正如我所期望的那样,有效位由 13 个十六进制数字 000010c6f7a0b 定义。

现在我转向 bash 并使用以下脚本:

#!/bin/bash
echo "hex read = 0x"$1
printf "hex       =%80.70a\n" "0x"$1
printf "hex -> dec=%80.70f\n" `echo "0x"$1`

GNU 重击 3.2.48

$ bash hex2dec 1.000010C6F7A0B5E1F
hex read = 0x1.000010C6F7A0B5E1F
hex       =   0x1.000010c6f7a0b000000000000000000000000000000000000000000000000000000000p+0
hex -> dec=        1.0000009999999999177333620536956004798412322998046875000000000000000000

所以一切都按我的预期工作:13 个十六进制数字定义了数字的有效位。

GNU 重击 4.1.5

$ bash hex2dec 1.000010C6F7A0B5E1F
hex read = 0x1.000010C6F7A0B5E1F
hex       =   0x8.00008637bd05af10000000000000000000000000000000000000000000000000000000p-3
hex -> dec=        1.0000009999999999993737856418540843606024282053112983703613281250000000

这不是我所期望的!

问题 1为什么在 GNU bash 4.1.5 中双精度数由 16 个十六进制数字表示(而不是根据 IEEE 754 的 13 个)?

问题 2为什么 printf "%a" 在不同的 bash 版本中以不同的格式表示十六进制数(bash 3.2.48 0x1.hh...hp+d 和bash 4.1.5 0xh.hh...hp+d?) . printf 不应该在两个 bash 版本中遵循相同的标准并由http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html重新定义吗?

4

1 回答 1

1

回答1目前bash在x86上的printflong double使用符合IEEE 754的输入/输出转换(参见Extended and extendable precision formatsx86 Extended Precision Format和bash的printf对floatmax_t的定义),类似于程序

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
    printf("%La\n", strtold("0x1.000010C6F7A0B5E1F", NULL));
}
  • 它的输出是0x8.00008637bd05af1p-3.

答案 2 Bash 最终使用 C 库的printf; 上面的 C 程序的输出确实遵循您所指的标准:

在小数点字符之前有一个十六进制数字(如果参数是规范化的浮点数,则该数字应为非零,否则未指定)

于 2013-07-26T06:32:11.610 回答