我想了解数字(双打)如何在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进行重新标记吗?
答案 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程序的输出符合您所指的标准:
在小数点字符之前有一个十六进制数字(如果参数是标准化的浮点数,则非零,未指定)