gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 16:35:54 24 4
gpt4 key购买 nike

是否有一个 printf 宽度说明符可以应用于浮点说明符,该说明符会自动将输出格式化为必要数量的有效数字,以便在扫描时字符串放回去,获取的是原来的浮点值?

例如,假设我将 float 打印到小数点后 2 位的精度:

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)

第二组是可以将字符串扫描为浮点然后打印 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-字符串-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/48704044/

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