在<float.h>中DECIMAL_DIG和LDBL_DIG之间有什么区别

时间:2016-09-26 13:03:31

标签: c floating-point

宏常量DECIMAL_DIG

  

可以转换为long double并返回而不会丢失精度的小数位数。

宏常量LDBL_DIG

  

可以在不失去long double精度的情况下表示的小数位数。

这两个定义有什么区别?是否存在使用一个而不是另一个可能导致错误结果的情况?

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

来源:1

3 个答案:

答案 0 :(得分:4)

  

DECIMAL_DIGLDBL_DIG(?)

之间有什么区别?

首先:缩小问题范围

DECIMAL_DIG(自C99起可用)适用于最宽浮点类型。对于C11,3种类型特定的宏FLT_DECIMAL_DIGDBL_DECIMAL_DIGLDBL_DECIMAL_DIG意味着相同的东西,除了它们适用于相应的类型,而不是最宽的。< / p>

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

十进制文字表示 - &gt; long double - &gt; 十进制文字表示
LDBL_DIG是此往返中始终产生相同起始值的文本的最大有效数字。

long double - &gt; 十进制文字表示 - &gt; long double
LDBL_DECIMAL_DIG是此往返所需文本的有效位数,始终会产生相同的起始long double值。

如果浮点类型使用基数10表示,LDBL_DIGLDBL_DECIMAL_DIG将具有相同的值。然而,大多数C实现使用二进制基数2而不是10:FLT_RADIX == 2

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

long double不能代表十进制文本表示所具有的每个可能值。后者可以是s = "0.1234567890123456789012345678901234567890",而常见long double也不能代表完全。将s转换为long double并返回文本预计不会返回相同的结果。

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

如果我们将文字输入限制为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

这篇文章Printf width specifier to maintain precision of floating-point value详细介绍了xxx_DECIMAL_DIG系列宏的使用情况。它显示了将浮点值打印到文本然后转换回FP值并始终获得相同结果所需的有效位数。

注意:xxx_DECIMAL_DIG >= xxx_DIG

上面使用的

LDBL_DIG - 1而不是LDBL_DIG作为%.*Le打印一个前导数字,然后输出指定的精确位数。总有效数字应为LDBL_DIG

答案 1 :(得分:1)

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

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

  • LDBL_DIG是从十进制转换为long double并返回时可靠保留的小数位数。 (对于特定情况,当然可以保留更多。)这是小数 - &gt; long double - &gt;十进制往返。

您引用的文字似乎具有误导性,可能完全错误,这是您对cppreference.com的期望。对于C或C ++的信息来说,这是一个非常糟糕的网站。

答案 2 :(得分:0)

<强> LBDL_DIG

  

可以舍入到浮点数并返回而不改变小数位数的小数位数。

  

小数位数q,这样任何带有q个十进制数字的浮点数都可以舍入为p基数为b的浮点数,然后再返回,而不会更改为q个十进制数字。

enter image description here

<强> DECIMAL_DIG

  

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

  

小数位数n,使得具有pmax基数b位的最宽支持浮点类型中的任何浮点数可以舍入为具有n个十进制数字的浮点数,并且可以再次返回而不更改该值。

enter image description here

回答OP的问题: 它们以不同的方式计算。公式如上所述,是造成差异的原因。

Source1 Source2 Useful url