%g printf说明符到底是什么意思? [英] What precisely does the %g printf specifier mean?
问题描述
%g
说明符的行为似乎不像大多数来源记录的那样.
The %g
specifier doesn't seem to behave in the way that most sources document it as behaving.
根据我发现的大多数资料,在使用printf
指示符的多种语言中,%g
指示符应等效于%f
或%e
-两者对于所提供的内容都会产生较短的输出价值.例如,在撰写此问题时, cplusplus.com 说,g
说明符的意思是:
According to most sources I've found, across multiple languages that use printf
specifiers, the %g
specifier is supposed to be equivalent to either %f
or %e
- whichever would produce shorter output for the provided value. For instance, at the time of writing this question, cplusplus.com says that the g
specifier means:
使用最短的表示形式:
%e
或%f
PHP手册说,它表示:
g-%e 和%f 中的较短者.
和这是一个堆栈溢出答案,其中声称
%g
使用最短的表示形式.
%g
uses the shortest representation.
和一个Quora答案声称:
%g
以这两种表示形式中的最短形式打印数字
%g
prints the number in the shortest of these two representations
但是这种行为不是我在现实中看到的.如果我编译并运行此程序(作为C或C ++,这是一个有效的程序,两者的行为相同):
But this behaviour isn't what I see in reality. If I compile and run this program (as C or C++ - it's a valid program with the same behaviour in both):
#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;
}
...然后我看到此输出:
... then I see this output:
1.234560e+05
123456.000000
123456
1.234567e+06
1234567.000000
1.23457e+06
很明显,对于上述x
或y
,%g
输出与 %e
或%f
输出都不完全匹配.而且,%g
看起来也不是使输出长度最小.如果y
像x
一样以科学计数法未印刷 ,则其格式可能更简洁.
Clearly, the %g
output doesn't quite match either the %e
or %f
output for either x
or y
above. What's more, it doesn't look like %g
is minimising the output length either; y
could've been formatted more succinctly if, like x
, it had not been printed in scientific notation.
我上面引用的所有消息来源对我来说都是骗人的吗?
Are all of the sources I've quoted above lying to me?
在支持这些格式说明符的其他语言中,我看到了相同或相似的行为,可能是因为它们在幕后呼唤了C函数的printf
系列.例如,我在Python中看到以下输出:
I see identical or similar behaviour in other languages that support these format specifiers, perhaps because under the hood they call out to the printf
family of C functions. For instance, I see this output in Python:
>>> print('%g' % 123456.0)
123456
>>> print('%g' % 1234567.0)
1.23457e+06
在PHP中:
php > printf('%g', 123456.0);
123456
php > printf('%g', 1234567.0);
1.23457e+6
在Ruby中:
irb(main):024:0* printf("%g\n", 123456.0)
123456
=> nil
irb(main):025:0> printf("%g\n", 1234567.0)
1.23457e+06
=> nil
控制此输出的逻辑是什么?
What's the logic that governs this output?
推荐答案
这是C11标准中的g
/G
说明符的完整描述:
This is the full description of the g
/G
specifier in the C11 standard:
表示浮点数的 double 参数是 转换为
f
或e
样式(对于G
,则转换为F
或E
样式 转换说明符),具体取决于转换后的值和 精确.如果 P 为非零,则等于精度;如果精度为0,则等于6. 省略;如果精度为零,则为1.然后,如果 样式E
的指数为 X :
A double argument representing a floating-point number is converted in style
f
ore
(or in styleF
orE
in the case of aG
conversion specifier), depending on the value converted and the precision. Let P equal the precision if nonzero, 6 if the precision is omitted, or 1 if the precision is zero. Then, if a conversion with styleE
would have an exponent of X:
如果 P > X ≥−4,则转换为
样式为f
(或F
),精度为 P −(X + 1).
否则,
转换采用样式e
(或E
)和精度 P − 1.
if P > X ≥ −4, the conversion is
with style f
(or F
) and precision P − (X + 1).
otherwise, the
conversion is with style e
(or E
) and precision P − 1.
最后,除非 使用#标志,将从分数中删除所有尾随零 结果的一部分和小数点字符将被删除,如果 没有剩余的小数部分.
Finally, unless the # flag is used, any trailing zeros are removed from the fractional portion of the result and the decimal-point character is removed if there is no fractional portion remaining.
一个 double 参数
表示无穷大或NaN的样式转换为f
或F
转换说明符.
A double argument
representing an infinity or NaN is converted in the style of an f
or F
conversion specifier.
此行为有点类似于仅使用%f
和%e
中的最短表示形式,但不等效.有两个重要的区别:
This behaviour is somewhat similar to simply using the shortest representation out of %f
and %e
, but not equivalent. There are two important differences:
- 使用
%g
时,尾随零(可能还有小数点)会被剥夺,这可能导致%g
说明符的输出与%f
或%e
将会产生. - 是否使用
%f
样式或%e
样式格式的决定完全基于%e
样式表示法所需的指数大小,并且 not 直接取决于哪种表示形式会更短.在多种情况下,此规则会导致%g
选择更长的表示形式,例如在问题中所示的情况,其中%g
使用科学计数法,即使这会使输出的4个字符超出所需的长度.
- Trailing zeros (and, potentially, the decimal point) get stripped when using
%g
, which can cause the output of a%g
specifier to not exactly match what either%f
or%e
would've produced. - The decision about whether to use
%f
-style or%e
-style formatting is made based purely upon the size of the exponent that would be needed in%e
-style notation, and does not directly depend on which representation would be shorter. There are several scenarios in which this rule results in%g
selecting the longer representation, like the one shown in the question where%g
uses scientific notation even though this makes the output 4 characters longer than it needs to be.
如果难以解析C标准的措辞,则 Python文档提供了相同行为的另一种描述:
In case the C standard's wording is hard to parse, the Python documentation provides another description of the same behaviour:
常规格式.对于给定的精度p
>=
1
, 这会将数字四舍五入为p
有效数字,并且 然后将结果格式化为定点格式 或以科学计数法表示,具体取决于其大小.
General format. For a given precisionp
>=
1
, this rounds the number top
significant digits and then formats the result in either fixed-point format or in scientific notation, depending on its magnitude.
精确的规则如下:假设
结果格式为演示文稿类型'e'
和
精度p-1
将具有指数exp
.然后
如果-4
<=
exp
<
p
,则数字已格式化
演示文稿类型'f'
和精度
p-1-exp
.否则,数字将被格式化
演示文稿类型为'e'
且精度为p-1
.
在这两种情况下,都删除了不重要的尾随零
从有效位开始,小数点也是
如果后面没有剩余数字,则将其删除.
The precise rules are as follows: suppose that the
result formatted with presentation type 'e'
and
precision p-1
would have exponent exp
. Then
if -4
<=
exp
<
p
, the number is formatted
with presentation type 'f'
and precision
p-1-exp
. Otherwise, the number is formatted
with presentation type 'e'
and precision p-1
.
In both cases insignificant trailing zeros are removed
from the significand, and the decimal point is also
removed if there are no remaining digits following it.
正负无穷大,正负无穷大
零和nans的格式为inf
,-inf
,
分别0
,-0
和nan
精度.
Positive and negative infinity, positive and negative
zero, and nans, are formatted as inf
, -inf
,
0
, -0
and nan
respectively, regardless of
the precision.
互联网上许多声称%g
只是从%e
和%f
中选出最短的消息来源都是错误的.
The many sources on the internet that claim that %g
just picks the shortest out of %e
and %f
are simply wrong.
这篇关于%g printf说明符到底是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!