【问题标题】:Is there a way to automatically printf a float to the number of decimal places it has?有没有办法自动将浮点数打印到它的小数位数?
【发布时间】:2021-02-04 04:09:25
【问题描述】:

我编写了一个程序来显示浮点数到适当的小数位数:

#include <stdio.h>

int main() {
    printf("%.2f, %.10f, %.5f, %.5f\n", 1.27, 345.1415926535, 1.22013, 0.00008);
}

有没有像%.(however many decimal places the number has)f 这样的转换字符,还是必须手动设置?

【问题讨论】:

  • 浮点值没有任何内在的东西可以确定它有多少个小数。您必须在运行时对其进行管理或对其进行硬编码。
  • 也许你想要的是从输出中删除尾随零? %g 会这样做。
  • FP 值没有小数位。它们有二元位置,两者不可通约。

标签: c floating-point


【解决方案1】:

有没有办法自动将浮点数打印到它的小数位数?

使用"%g""%g" 去掉尾随的零位。

... 除非使用 # 标志,否则将从结果的小数部分删除任何尾随零,如果没有剩余小数部分,则删除小数点字符。 C17dr § 7.21.6.1 8.

所有有限浮点值都可以用十进制精确表示 - 有些需要很多数字才能精确打印。从&lt;float.h&gt;DBL_DECIMAL_DIG(通常为17)位有效数字就足够了——很少需要更多。

传递精度以鼓励足够的输出,但不要太多。

请记住,0.00008 之类的值并不完全编码为典型的二进制浮点 double,而是使用了一个附近的值,例如 8.00000000000000065442...e-05

printf("%.*g\n", DBL_DECIMAL_DIG, some_double);

printf("%.17g, %.17g, %.17g, %.17g\n", 1.27, 345.1415926535, 1.22013, 0.00008);
// 1.27, 345.14159265350003, 1.2201299999999999, 8.0000000000000007e-05

DBL_DIG(例如 15)可能更好地满足 OP 的目标。

printf("%.15g, %.15g, %.15g, %.15g\n", 1.27, 345.1415926535, 1.22013, 0.00008);
// 1.27, 345.1415926535, 1.22013, 8e-05

打印double - exactly 的函数可能需要 100 位数字。

【讨论】:

  • 您需要的有效十进制位数正好等于浮点格式的有效位数中的有效位数,IEEE double 是 53 位。但是,您必须在小数点后添加前导零的数量。
  • @MarkRansom "您需要的有效十进制位数正好等于浮点格式的有效位数中的有效位数,对于 IEEE 双精度为 53 位" -->不同意需要 53 个十进制数字。更像 53*log(2) + 几个有效数字就足够了。 准确地 表示像DBL_MIN 这样的分数所需的小数位数是指数的函数,而不是有效数。建议发布一个详细说明您的想法的答案。
  • 指数正是我添加免责声明的原因,即您需要添加前导零。
  • @MarkRansom 我不明白你的评论。如果是为了精确打印,2^-n 是 5^n/10^n。 5^n 可以跨越许多位(双精度的最小位是 2^-1074,5^1074 需要许多小数位,不考虑前导零)。如果有效意味着足够多的数字使浮点无法区分,那么 53 就太多了。
  • 因为 2 是 10 的质因数,所以我认为每个以 10 为底的数字将覆盖以 2 为底的数字。多年来,我已经多次测试过这个假设,并且一直坚持到今天。我发现 0.05 需要 55 位数字,随着数字变小,问题越来越大。我将不得不重新检查导致我错误结论的数学。同时,请忽略我上面所说的一切。
【解决方案2】:

sprintf() 可以帮助您
根据我的经验,没有直接的方法可以做到这一点
这是一个简单的算法来帮助你完成这个功能

munber = float/double input
n = number of decimal places in float/double
char format[999];
sprintf(format ,"%%.%df" ,n);
printf(format, number);

sprintfprintf 类似,但sprintf 不是写入stdout,而是写入一个字符串。

现在您需要找到精度后的位数。

【讨论】:

  • 您好 Mukul,感谢您的回答,我对编程很陌生,很难理解您的回答。你能解释一下你的代码的不同部分在做什么吗?对不起,我的无知。
  • 构建格式字符串是一团糟,它使静态分析很难捕捉到错误,这里绝对不需要它,printf("%.*f", n, number); 会做同样的事情
  • @M.M 你能详细说明它是如何工作的吗?
  • char format[99];"%%.%df" 不足以打印所有 doublesprintf(format ,"%%.%df" , DBL_MAX); 导致 UB 像缓冲区溢出..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 2023-02-03
  • 1970-01-01
  • 1970-01-01
  • 2011-02-02
相关资源
最近更新 更多