谁能解释一下printf中的[.precision]是如何与说明符"%g“一起工作的?我对下面的输出感到非常困惑:
double value = 3122.55;
printf("%.16g\n", value); //output: 3122.55
printf("%.17g\n", value); //output: 3122.5500000000002我了解到%g使用最短的表示形式。
但是下面的输出仍然让我感到困惑
printf("%.16e\n", value); //output: 3.1225500000000002e+03
printf("%.16f\n", value); //output: 3122.5500000000001819
printf("%.17e\n", value); //output: 3.12255000000000018e+03
printf("%.17f\n", value); //output: 3122.55000000000018190我的问题是:为什么%.16g给出了确切的数字,而%.17g不能?
看起来16位有意义的数字可能是准确的。有人能告诉我原因吗?
发布于 2015-06-05 13:31:42
%g使用最短的表示。
浮点数usually aren't stored作为基数10中的一个数,但2 (性能、大小、实用性原因)。然而,无论您的表示基础是什么,总会有一些有理数无法在变量存储它们的任意大小限制下表示。
当您指定%.16g时,您的意思是希望给定数字的最短表示形式具有最多16个有效位数。
如果最短表示的位数超过16位,printf将通过剪切最后的2位数来缩短数字字符串,留下3122.550000000000,它实际上是最短形式的3122.55,解释您获得的结果。
一般来说,%g总是会给你尽可能短的结果,这意味着如果代表你的数字的数字序列可以在不损失任何精度的情况下被缩短,它就会被缩短。
为了进一步说明这个示例,当您使用%.17g并且17的小数位包含一个与0不同的值(特别是2)时,您最终得到的是完整的数字3122.5500000000002。
我的问题是:为什么
%.16g给出了确切的数字,而%.17g不能?
实际上是%.17g给出了确切的结果,而%.16g只给出了一个四舍五入的近似值和一个误差(与内存中的值相比)。
如果需要更固定的精度,请改用%f或%F。
发布于 2019-01-13 02:10:45
十进制值3122.55不能用二进制浮点精确表示。当你写的时候
double value = 3122.55;您最终得到了可以精确表示的最接近的值。碰巧的是,这个值正好是3122.5500000000001818989403545856475830078125。
16个有意义的数字的值是3122.550000000000。对于17个有意义的数字,它是3122.5500000000002。这些就是%.16g和%.17g给你的表示。
请注意,十进制数的最接近的double表示保证至少精确到15个十进制有效数字。这就是为什么在这种情况下,您需要打印到16或17位才能在输出中看到这些明显的错误-对于任何较小数量的有效数字,double表示都保证与您键入的原始十进制数相匹配。
最后一点:你可以这么说
我了解到
%g使用最短的表示法。
虽然这是对%g行为方式的流行总结,但它也是错误的。参见What precisely does the %g printf specifier mean?,我在那里详细讨论了这一点,并展示了一个使用科学记数法的%g示例,尽管它比不使用科学记数法要长4个字符。
发布于 2019-01-13 02:47:15
十进制表示法3122.55不能由二进制浮点表示法精确表示。
双精度二进制浮点值可以正确地表示十进制值的大约15个有效数字(注意,不是小数位);此后,这些数字可能不相同,并且在极端情况下甚至没有任何实际意义,并且将是从浮点表示到十进制数字串转换的伪像。
我了解到%g使用最短的表示。
规则是:
其中P是精度(如果没有指定精度,则为6;如果精度为零,则为1),而X是E/e样式表示法所需的十进制指数,则:
修改%g的精度会导致以下结果的不同输出:
printf("%.16g\n", value); //output: 3122.55
printf("%.16e\n", value); //output: 3.1225500000000002e+03
printf("%.16f\n", value); //output: 3122.5500000000001819尽管在格式说明符中具有相同的精度。
https://stackoverflow.com/questions/30658919
复制相似问题