%g printf说明符到底是什么意思?

时间:2019-01-12 17:31:51

标签: c floating-point language-agnostic printf format-specifiers

%g说明符的行为似乎不像大多数来源将其记录为行为那样。

根据我发现的大多数资料,在使用printf指示符的多种语言中,%g指示符应等效于%f%e-对于提供的值,无论哪种都会产生较短的输出。例如,在撰写此问题时,cplusplus.com says g说明符的意思是:

  

使用最短的表示形式:%e%f

PHP manual says的意思是:

  

g-%e %f 中的较短者。

here's a Stack Overflow answer声称

  

%g使用最短的表示形式。

还有a Quora answer声称:

  

%g以这两种表示形式中的最短形式打印数字

但是这种行为不是我在现实中看到的。如果我编译并运行该程序(作为C或C ++,这是一个有效的程序,两者的行为相同):

#include <stdio.h>

int main(void) {
    double x = 123456.0;
    printf("%e\n", x);
    printf("%f\n", x);
    printf("%g\n", x);
    printf("\n");

    double y = 1234567.0;
    printf("%e\n", y);
    printf("%f\n", y);
    printf("%g\n", y);
    return 0;
}

...然后我看到此输出:

1.234560e+05
123456.000000
123456

1.234567e+06
1234567.000000
1.23457e+06

很显然,%g或{{1}的%e输出与%fx的输出都不完全匹配。 } 以上。而且,y似乎也没有使输出长度最小化。如果%gy一样 不是以科学计数法印刷的,那么本可以更简洁地格式化。

我在上面引用的所有消息来源都是骗我的吗?

在支持这些格式说明符的其他语言中,我看到了相同或相似的行为,可能是因为它们在幕后呼唤了x C函数家族。例如,我在Python中看到以下输出:

printf

在PHP中:

>>> print('%g' % 123456.0)
123456
>>> print('%g' % 1234567.0)
1.23457e+06

在Ruby中:

php > printf('%g', 123456.0);
123456
php > printf('%g', 1234567.0);
1.23457e+6

控制此输出的逻辑是什么?

2 个答案:

答案 0 :(得分:13)

这是C11标准中的g / G说明符的完整描述:

  

表示浮点数的 double 参数是   以fe样式转换(或在F情况下以EG样式转换   转换说明符),具体取决于转换后的值和   精确。如果 P 等于非零精度,则为6,如果精度为   省略;如果精度为零,则为1。然后,如果   样式E的指数为 X

     

如果 P > X ≥−4,则转换为   样式为f(或F),精度为 P −(X + 1)
  否则,   转换采用样式e(或E)和精度 P − 1。

     

最后,除非   使用标志,将从分数中删除所有尾随零   结果的一部分和小数点字符将被删除,如果   没有剩余的小数部分。

     

double 自变量   表示无穷大或NaN的形式转换为fF   转换说明符。

此行为有点类似于简单地使用%f%e中最短的表示形式,但并不等效。有两个重要区别:

  • 使用%g时,尾随零(可能还有小数点)会被剥夺,这可能导致%g说明符的输出与两者都不完全匹配。 %f%e就会产生。
  • 是否使用%f样式或%e样式格式的决定完全基于%e样式表示法所需的指数大小,并且不是 not 直接取决于哪种表示形式会更短。在几种情况下,此规则会导致%g选择更长的表示形式,就像问题中显示的那样,%g使用科学计数法,即使这会使输出的4个字符长于所需的长度。 。

万一C标准的措辞难以解析,Python documentation将提供对相同行为的另一种描述:

常规格式。对于给定的精度p >= 1, 这会将数字四舍五入为p个有效数字,并且 然后将结果格式化为定点格式 或以科学计数法表示,具体取决于其大小。

精确的规则如下:假设 结果格式为演示文稿类型>=,并且 精度1将具有指数p。然后 如果为p,则数字被格式化 演示文稿类型为'e',精度高 'e'。否则,数字将被格式化 展示类型为p-1,精度为p-1。 在这两种情况下,不重要的尾随零均被删除 从有效位开始,小数点也是 如果后面没有剩余数字,则将其删除。

正负无穷大,正负无穷大 零和nans的格式分别为expexp, 不论-4 <= exp < p-4<=如何 精度。

精度exp被视为等同于 <的精度。默认精度为p

互联网上许多声称'f'只是从'f'p-1-exp中选出最短的消息来源都是错误的。

答案 1 :(得分:-6)

我最喜欢的双打格式是“%.15g”。似乎在每种情况下都做对了。我很确定15也是两倍的最大可靠十进制精度。

相关问题