C++ 为什么mpfr_printf与十六进制浮点(%a转换说明符)的printf不同?

C++ 为什么mpfr_printf与十六进制浮点(%a转换说明符)的printf不同?,c++,floating-point,mpfr,C++,Floating Point,Mpfr,我正在比较来自常规浮点运算的值,并使用高精度MPFR数作为基线。打印时,我不明白为什么下面的代码输出不同 表示输出说明符是 “a”“a”十六进制浮点,C99样式 所以我假设它打印的和printf一样。然而,情况并非如此: 包括 包括 使用名称空间boost::multiprecision; int main int argc,char*argv[] { 双a=254.5; mpfr_浮点数_1000 mpfr_a=254.5; mpfr\t; mpfr_init2t,3324;//1000十进制

我正在比较来自常规浮点运算的值,并使用高精度MPFR数作为基线。打印时,我不明白为什么下面的代码输出不同

表示输出说明符是

“a”“a”十六进制浮点,C99样式

所以我假设它打印的和printf一样。然而,情况并非如此:

包括 包括 使用名称空间boost::multiprecision; int main int argc,char*argv[] { 双a=254.5; mpfr_浮点数_1000 mpfr_a=254.5; mpfr\t; mpfr_init2t,3324;//1000十进制精度 mpfr\u集合dt,a,mpfr\u RNDN; printfdouble:\t%a\n,a; mpfr\u printfmpfr\u t:\t%RNa\n,t; mpfr\u printfboost:\t%RNa\n,mpfr\u a; } 给出输出:

double: 0x1.fdp+7
mpfr_t: 0xf.e8p+4
boost:  0xf.e8p+4
这没什么大不了的,因为sscanf将它们解析为相同的值,但我找不到任何文档来解释它们为什么不同


哪一个是规范的?

没有规范形式。C标准不规定第一位数字,但对于正常数字,第一位数字必须为非零。C 2018 7.21.6.1第8节规定了a和a转换规范:

表示浮点数的双参数转换为[-]0xh.hhhp±d,其中,如果参数是标准化浮点数,则有一个十六进制数字为非零,并且在小数点字符之前未指定,在小数点字符之后的十六进制数字数等于精度


为了完成关于缺少规范形式的答案,我试图给出各种选择

对于GNU libc,stdio common/printf_fphex.c包含:

  /* We have 52 bits of mantissa plus one implicit digit.  Since
     52 bits are representable without rest using hexadecimal
     digits we use only the implicit digits for the number before
     the decimal point.  */
但请注意,并非所有格式都使用隐式位:x86上的x87扩展精度格式long double不使用隐式位。因此,这可能会产生一些不一致性

对于printf POSIX实用程序,我在2007年对printf%a\n 256进行的测试显示了3种不同的结果:

0x1p+8,Linux/x86下的bash 3.1.17和Mac OS X PPC 10.4.11下的bash 2.05b.0的printf内置; 0x2p+7,带有Mac OS X PPC 10.4.11下coreutils 6.9的printf; 0x8p+5,带有Linux/x86下coreutils 5.97中的printf。 关于GNU MPFR,最初的选择是使第一个数字尽可能大,即在8和15=F之间,这允许获得尽可能短的有效位字符串。但这似乎已更改为指数为4的倍数,除非精度字段为0。我不知道为什么