当前位置: 首页 > 知识库问答 >
问题:

使用说明符“%g”的printf的精度

邵兴怀
2023-03-14

有人能解释一下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个有效数字是准确的。有人能告诉我原因吗?

共有1个答案

云煌
2023-03-14

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

浮点数通常不存储在基础10中,而是存储在2中(性能、大小和实用性方面的原因)。然而,无论表示的基础是什么,总有一些有理数不能用变量的任意大小限制来表示来存储它们。

当您指定%.16g时,您表示您想要给定数字的最短表示形式,最多16有效数字。

如果最短的表示形式超过16位数,printf将通过在最末尾剪切2位数来缩短数字字符串,从而使您得到3122.5500000000,实际上是3122.55,以最短的形式说明所获得的结果。

通常,%g总是给出尽可能短的结果,这意味着如果可以在不损失精度的情况下缩短表示数字的数字序列,就可以完成。

为了进一步说明这个示例,当您使用%.17g并且17第十位小数点包含一个不同于0(特别是2)的值时,您将得到完整的数字3122.55000000002

我的问题是:为什么%.16g能给出确切的数字,而%.17g不能?

实际上是%.17g给出了准确的结果,而%.16g只给出了带错误的舍入近似值(与内存中的值相比)。

如果需要更固定的精度,请改用%f%f

 类似资料:
  • 有了,我可以使用表示

  • 由于ANSI C99,通过有或。但是bool是否也有格式说明符? 它将打印:

  • 假设我有以下功能: 我希望调用者指定要打印的浮点数,以及小数点后的位数。(由<代码>表示)。%d说明符) 然而,在编译此代码时,我收到两个警告: 和 我的问题是:如何将格式说明符(例如本例中的)注入现有格式说明符?

  • 问题内容: 遇到一个有趣的面试问题: 尽管这在某些系统上可能运行良好,但至少我的系统出现了分段错误。对此行为的最佳解释是什么?上面的代码在C中。 以下是我的gcc信息: 问题答案: 首先,第一件事是:期望其%s参数使用有效的(即非NULL)指针,因此将NULL正式传递给它是不确定的。它可能会显示“(null)”,也可能会删除硬盘上的所有文件- 就ANSI而言,这是正确的行为(至少,这是Harbis

  • 问题内容: 下面是我以前如何将浮点数截断到两位小数 我检查了文档和电子书,但无法弄清楚。谢谢! 问题答案: 根据David的回答,到目前为止,我最好的解决方案是 我认为这是最类似于Swift的解决方案,将格式化操作直接与数据类型相关联。可能是某处有一个内置的格式化操作库,或者它可能很快就会发布。请记住,该语言仍处于测试阶段。

  • 这是部分源代码(来自《C primer plus》一书的示例代码): 预期输出为: 这本书明确解释了原因: 参数传递机制取决于实现。这就是参数传递在一个系统上的工作方式。函数调用如下: 此调用告诉计算机将变量n1、n2、n3和n4的值移交给计算机。这里有一种常见的实现方法。程序将值放在称为堆栈的内存区域中。当计算机将这些值放在堆栈中时,它是由变量类型而不是转换说明符引导的。因此,对于n1,它在堆栈