gpt4 book ai didi

c - 用于保持浮点值精度的 Printf 宽度说明符

转载 作者:太空狗 更新时间:2023-10-29 16:15:35 24 4
gpt4 key购买 nike

是否有 printf 宽度说明符可以应用于浮点说明符,自动将输出格式化为必要数量的有效数字,以便在扫描string 回来,得到的是原来的浮点值?

例如,假设我打印一个 float2 小数位的精度:

float foobar = 0.9375;
printf("%.2f", foobar); // prints out 0.94

当我扫描输出 0.94 时,我没有符合标准的保证我会得到原始的 0.9375 浮点值(在这个例子中,我可能不会)。

我想要一种方法告诉 printf 自动将浮点值打印到必要的有效数字数以确保它可以被扫描回原始值传递给 printf 的值。

我可以使用 float.h 中的一些宏来 derive the maximum width传递给 printf,但是是否已经有一个说明符可以自动打印到必要数量的有效数字——或者至少打印到最大宽度?

最佳答案

我推荐@Jens Gustedt 十六进制解决方案:使用 %a。

OP 希望“以最高精度打印(或至少到最重要的小数点)”。

一个简单的例子是打印七分之一,如下所示:

#include <float.h>
int Digs = DECIMAL_DIG;
double OneSeventh = 1.0/7.0;
printf("%.*e\n", Digs, OneSeventh);
// 1.428571428571428492127e-01

但让我们深入挖掘......

从数学上讲,答案是“0.142857 142857 142857 ...”,但我们使用的是有限精度 float 。让我们假设 IEEE 754 double-precision binary .所以 OneSeventh = 1.0/7.0结果如下。还显示了前后可表示的 double float 。

OneSeventh before = 0.1428571428571428 214571170656199683435261249542236328125
OneSeventh = 0.1428571428571428 49212692681248881854116916656494140625
OneSeventh after = 0.1428571428571428 769682682968777953647077083587646484375

打印 double精确十进制表示用途有限。

C 在 <float.h> 中有 2 个宏系列帮助我们。
第一组是要在字符串中以十进制形式打印的 有效 位数,因此当向后扫描字符串时,我们得到了原始的 float 。显示了 C 规范的最小值和一个示例 C11 编译器。

FLT_DECIMAL_DIG   6,  9 (float)                           (C11)
DBL_DECIMAL_DIG 10, 17 (double) (C11)
LDBL_DECIMAL_DIG 10, 21 (long double) (C11)
DECIMAL_DIG 10, 21 (widest supported floating type) (C99)

第二组是字符串可能被扫描成 float 的有效位数,然后打印 FP,仍然保留相同的字符串表示形式。显示了 C 规范的最小 值和一个示例 C11 编译器。我相信在 C99 之前可用。

FLT_DIG   6, 6 (float)
DBL_DIG 10, 15 (double)
LDBL_DIG 10, 18 (long double)

第一组宏似乎符合 OP 的有效 数字目标。但该并不总是可用。

#ifdef DBL_DECIMAL_DIG
#define OP_DBL_Digs (DBL_DECIMAL_DIG)
#else
#ifdef DECIMAL_DIG
#define OP_DBL_Digs (DECIMAL_DIG)
#else
#define OP_DBL_Digs (DBL_DIG + 3)
#endif
#endif

“+ 3”是我之前回答的关键。它的中心是如果知道往返转换字符串-FP-字符串(设置 #2 宏可用 C89),如何确定 FP-string-FP 的数字(设置 #1 宏在 C89 后可用)?一般来说,加 3 就是结果。

现在有多少重要的 数字要打印是已知的,并通过<float.h> 驱动.

要打印 N 个 有效 十进制数字,可以使用各种格式。

"%e"精度 字段是前导数字和小数点之后 的位数。所以- 1一切顺利。注:本-1不在初始 int Digs = DECIMAL_DIG;

printf("%.*e\n", OP_DBL_Digs - 1, OneSeventh);
// 1.4285714285714285e-01

"%f"精度 字段是小数点 后的位数。对于像 OneSeventh/1000000.0 这样的数字,需要 OP_DBL_Digs + 6查看所有有效数字。

printf("%.*f\n", OP_DBL_Digs    , OneSeventh);
// 0.14285714285714285
printf("%.*f\n", OP_DBL_Digs + 6, OneSeventh/1000000.0);
// 0.00000014285714285714285

注意:许多用于"%f" .即显示小数点后6位; 6 是显示默认值,不是数字的精度。

关于c - 用于保持浮点值精度的 Printf 宽度说明符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16839658/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com