在bash中使用十六进制数字的bash和printf表示数字

时间:2013-02-01 07:42:51

标签: bash double printf hex

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

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

为了检查它,我写了一个简单的C程序,它将hex转换为dec(使用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

从这个结果我得出结论,正如我所期望的那样,有效数据由十六进制数字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 bash 3.2.48

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

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

GNU bash 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 double的有效数字由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进行重新标记吗?

1 个答案:

答案 0 :(得分:1)

答案1 x86上的当前bash printf使用long double进行输入/输出转换,符合IEEE 754(参见Extended and extendable precision formats,{{3和bash的printf定义x86 Extended Precision Format),类似于程序

#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程序的输出符合您所指的标准:

  

在小数点字符之前有一个十六进制数字(如果参数是标准化的浮点数,则非零未指定