<float.h>中的DECIMAL_DIG和LDBL_DIG有什么区别

And*_*lay 3 c floating-point

宏常量DECIMAL_DIG

可以在long double不损失精度的情况下往返转换的小数位数。

宏常量LDBL_DIG

可以代表的小数位数,而不会降低的精度long double

这两个定义有什么区别?有没有一种情况可能导致错误的结果?

在我的机器上DECIMAL_DIG == 21,而LDBL_DIG == 18

资料来源:1

chu*_*ica 5

DECIMAL_DIGLDBL_DIG(?)有什么区别?

第一:缩小问题

DECIMAL_DIG(自C99起可用)适用于最宽的浮点类型。随着C11,3个型专用宏FLT_DECIMAL_DIGDBL_DECIMAL_DIGLDBL_DECIMAL_DIG意思是一样的,除了它们适用于相应的类型,而不是最广泛的一个。

为了简化问题,让我们比较一下LDBL_DECIMAL_DIGLDBL_DIG因为它们都处理相同的类型:long double


十进制文本表示 -> long double-> 十进制文本表示
LDBL_DIG是在此往返过程中始终导致相同起始值的文本的最大有效数字。

long double-> 十进制文本表示形式 -> long double
LDBL_DECIMAL_DIG是在此往返过程中始终产生相同起始值 所需的有效数字位数long double

如果浮点类型中使用的基体10的介绍,LDBL_DIG并且LDBL_DECIMAL_DIG将具有相同的值。然而,大多数C实现使用二进制基座2而不是10: FLT_RADIX == 2


以下避免了深入的数学技术解释。

long double不能代表十进制文本表示形式所能代表的所有可能值。后者可以s = "0.1234567890123456789012345678901234567890"和普通long double不能代表准确。转换slong double文本和返回文本不会返回相同的结果。

char *s = "0.1234567890123456789012345678901234567890";
long double ld = strtold(s, (char **)NULL);
printf("%.40Le\n", ld);
// typical output        v -- different
// 1.2345678901234567890132180073559098332225e-01
Run Code Online (Sandbox Code Playgroud)

如果我们将文本输入限制为LDBL_DIG 有效数字,则对于long double-往返的所有值,代码将始终成功。

s = "0.123456789012345678";
ld = strtold(s, (char **)NULL);
printf("%d\n%.*Le\n", LDBL_DIG, LDBL_DIG - 1, ld);
// 18
// 1.23456789012345678e-01
Run Code Online (Sandbox Code Playgroud)

这篇用于保持浮点值精度的Printf宽度说明符详细介绍了xxx_DECIMAL_DIG一系列宏的用法。它显示了将浮点值打印到文本,然后转换回FP值并始终获得相同结果所需的有效位数。


注:xxx_DECIMAL_DIG >= xxx_DIG

LDBL_DIG - 1以上,而不是用来LDBL_DIG作为%.*Le打印的领先数字,然后数字指定的精度数。总有效数字应为LDBL_DIG


R..*_*R.. 5

他们正在处理相反的往返方向。

  • DECIMAL_DIG是从最大浮点类型转换为十进制字符串并返回时所需的十进制位数,以确保返回相同的值。(当然,对于特定值,您可能可以使用更少的数字来获得,但如果您想要适用于任何值的数字位数,DECIMAL_DIG就是这样。)这是long double-> 小数 ->long double往返。

  • LDBL_DIG是在十进制相互转换时可靠保留的十进制位数long double。(当然,对于特定情况,可以保留更多。)这是小数 -> long double-> 小数往返。

您引用的文本似乎具有误导性,并且可能完全错误,这正是您应该从 cppreference.com 获得的结果。这是一个关于 C 或 C++ 信息的非常糟糕的网站。


xen*_*ros 0

LBDL_DIG

可以在不改变小数位数的情况下四舍五入为浮点数并四舍五入为浮点数的小数位数。

小数位数 q,使得任何具有 q 位十进制数字的浮点数都可以四舍五入为具有 p 基数 b 位的浮点数,然后再四舍五入,而不更改为 q 个十进制数字。

在此输入图像描述

DECIMAL_DIG

可以四舍五入为浮点类型并再次返回到相同十进制数字的小数位数,而不会损失精度。

小数位数 n,使得具有 pmax 基数 b 位的最广泛支持的浮点数中的任何浮点数都可以四舍五入为具有 n 个小数位的浮点数,并且可以在不更改值的情况下再次舍入。

在此输入图像描述

回答OP的问题:它们的计算方式不同。上面附有公式,它们是差异的原因。

来源1 来源2 有用的网址