解释 printf("%# 01.1g",9.8) 中的格式说明符

ein*_*ica 6 c floating-point printf format-specifiers language-lawyer

考虑以下 printf 指令:

\n
printf("%# 01.1g", 9.8);\n
Run Code Online (Sandbox Code Playgroud)\n

它应该打印什么?

\n

我正在 cppreference.com 上阅读g说明符的描述,其中显示(已删除的文本G):

\n
\n

根据值和精度将浮点数转换为十进制或十进制指数表示法。

\n

对于g转换,将执行带有ef样式的样式转换。
如果非零,则令 P 等于精度;如果未指定精度,则令 P 等于精度;如果精度为 \xe2\x80\x8b0\xe2\x80\x8b,则令 P 等于精度。那么,如果使用e类型的\n转换将具有 X 的指数:

\n
    \n
  • 如果 P > X \xe2\x89\xa5 \xe2\x88\x924,则转换采用样式f和精度 P \xe2\x88\x92 1 \xe2\x88\x92 X。
  • \n
  • 否则,转换采用样式e和精度 P \xe2\x88\x92 1。
  • \n
\n

除非请求替代表示,否则尾随零将被删除,如果没有留下小数部分,小数点字符也会被删除。

\n
\n

在我们的例子中,

\n
    \n
  • P = 1 ,明确指定。
  • \n
  • X = 0,因为“使用样式e的转换”,即"%# 01.1e",产生 9.8e+00(调整 GodBolt 程序,你会看到)。
  • \n
  • 1 > 0 >= -4 成立。
  • \n
\n

因此,转换应采用样式f和精度 P - 1 - X = 1 - 1 - 0 = 0,即"%# 01.0f",产生 10.

\n

...但这不是glibc产生的结果:我得到了 1.e01,也可以在 上看到GodBolt

\n

所以,

\n
    \n
  • 我是否误读了引用的文字?
  • \n
  • cppreference.com 是否有误?
  • \n
  • 这是--灭亡--glib 2.36 的错误吗?
  • \n
\n

Eri*_*hil 2

这是对 \xe2\x80\x9ca 与样式 \xe2\x80\x9d 的转换缺乏明确性,并且与和E的精度含义存在差异。Eg

\n

使用 时E,精度是小数点后出现的位数,根据 C 2018 7.21.6.1 4。使用 时g,精度是有效数字的最大位数。这些不同;E小数点前有一位额外的数字,总共比其名义 \xe2\x80\x9c 精度多一位数字。\xe2\x80\x9d

\n

因此,在考虑如何为 格式化 9.8 时%.1g,我们首先考虑如何将%.0E、 not 、 格式化为%.1E%.1g%.0E要求一位数字,而%.1E要求两位数字。对于%.0E,将生成 \xe2\x80\x9c1e+01\xe2\x80\x9d 。所以指数X是 1,而不是 0。

\n