提问人:einpoklum 提问时间:7/11/2023 最后编辑:einpoklum 更新时间:7/11/2023 访问量:143
解释 printf(“%# 01.1g”,9.8) 中的格式说明符
Interpreting the format specifier in printf("%# 01.1g",9.8)
问:
请考虑以下 printf 指令:
printf("%# 01.1g", 9.8);
它应该打印什么?
我正在阅读 cppreference.com 上 g 说明符的描述,上面写着(删除的文本):G
根据值和精度将浮点数转换为十进制或十进制指数表示法。
对于 g 转换样式,样式为 e 或 f 的样式转换将是 执行。
设 P 等于非零的精度,如果 未指定精度,如果精度为 0,则为 1。然后,如果 使用样式 e 的转换将具有 X 的指数:
- 如果 P > X ≥ −4,则转换采用样式 f 和精度 P − 1 − X。
- 否则,转换的样式为 e,精度为 P − 1。
除非请求替代表示,否则尾随的零为 删除,如果没有小数,也会删除小数点字符 部分还剩下。
在我们的例子中,
- P = 1 ,明确指定。
- X = 0,因为“样式为 e 的转换”,即 ,产生(调整 GodBolt 程序,你会看到)。
"%# 01.1e"
9.8e+00
- 1 > 0 >= -4 个成立。
因此,转换应使用样式 f 和精度 P - 1 - X = 1 - 1 - 0 = 0,即 ,其产生 。"%# 01.0f"
10.
...但这不是 glibc 产生的:我明白了,正如在 GodBolt 上看到的那样。 1.e01
所以
- 我是否误读了引用的文本?
- cppreference.com 错了吗?
- 这是 - 灭亡 tought - 一个油嘴滑舌的 2.36 错误吗?
答:
这是对“有风格的转换”缺乏明确性,并且对精度的含义和存在差异。E
E
g
使用 ,精度是小数点后出现的位数,根据 C 2018 7.21.6.1 4。其中 ,精度为最大有效位数。这些不同; 在小数点之前有一个额外的数字,总共比其名义上的“精度”多一个数字。E
g
E
因此,在考虑如何格式化 9.8 时,我们首先考虑如何格式化为 ,而不是 ,因为两者都请求一个数字,而请求两个数字。对于 ,将产生 “1e+01”。所以 X,指数,是 1,而不是 0。%.1g
%.0E
%.1E
%.1g
%.0E
%.1E
%.0E
评论
g
e
e
f
根据C标准(草案),精度是指
和 转换的最大有效位数
g
G
精度为 1,这意味着该值将四舍五入到一个有效数字(9.8 四舍五入为 10)。"%# 01.1g"
现在让我们看一下同一标准草案中的定义:g
表示浮点数的参数将转换为 style 或(或 in style 或在转换说明符的情况下), 取决于转换后的值和精度。设 P 等于 如果不为零,则为 precision,如果省略精度,则为 6,如果精度为零,则为 1。 然后,如果具有样式的转换的指数为 X:
double
f
e
F
E
G
E
- 如果 P > X ≥ −4,则转换为样式 (或 ) 和精度 P − (X + 1)。
f
F
- 否则,转换为样式 (或 ) 和精度 P − 1。
e
E
在我们的例子中,P = 1(精度),X = 1(1e+01 的指数,指数格式为 10)
P > X 为 false,因此“否则”子句生效,这意味着应使用指数格式。
所以 glibc 和 cppreference 都是正确的,事实上后者似乎直接基于标准。
评论