在 C 中打印双浮点数时,是否有定义非有效数字限制的宏?

Is there a macro that defines the limit of non-significant digits when printing a double floating point number in C?

提问人:Valeria Suarez 提问时间:10/25/2023 最后编辑:Fe2O3Valeria Suarez 更新时间:10/25/2023 访问量:69

问:

当使用具有大精度和双浮点数的 printf 时,在非有效数字上会发生舍入(当尾随 0 开始时)。我想知道是否有定义位数限制/数量的宏。

#include <stdio.h>
#include <float.h>

int main() {
    const double x = 2.0 / 3.0;
    int precision = 100;
    printf("%.*f\n", precision, x);
    printf("%d\n", DBL_DECIMAL_DIG);

    return 0;
}

输出为:

0.6666666666666666296592325124947819858789443969726562500000000000000000000000000000000000000000000000
17

重复的 6 是有效数字,而后面的数字是非有效数字,然后在某个点四舍五入(这个点在哪里定义?),然后是重复的 0。

C 运行时 libc

评论

0赞 Eric Postpischil 10/25/2023
对于使用以 2 为基数的浮点格式,舍入发生在数字的二进制表示形式上,而不是十进制数字上。从数学上讲,没有用于此目的的“有效”或“非有效”十进制数字。有一个宏告诉一个数字到浮点数的单次转换可以保留多少个十进制数字,但这并不能告诉你其他操作的计算结果中有多少位是“显著的”或“正确的”,因为舍入误差可以复合或抵消,使最终误差从零到无穷大, 视情况而定。
1赞 Eric Postpischil 10/25/2023
@user3386109:如果问题是零必须从哪里开始,并且是 2,那么由于所涉及的数学性质,有一个宏给出它。FLT_RADIXDBL_MANT_DIG
1赞 user3386109 10/25/2023
@EricPostpischil 确实如此,但前提是设置了 ULP。也许只有当数字在 0.5 到 1.0 之间时(指数对位数的影响对我来说并不完全清楚)。
1赞 user3386109 10/25/2023
粗略地说,当指数大于 1 时,每个小数二进制位增加 1 个小数十进制数字,但每个整数十进制数字平均需要大约 3.3 个整二进制位。因此,零之前的位数随着指数的增加而减少。
1赞 Simon Goater 10/25/2023
如果数字 x = b.c,其中 b 和 c 是二进制表示,则打印时的最后一个十进制数字位于 c 中最后一个设置位的位置。对于 IEEE 754,您可以通过知道尾数的大小来获得上限,并通过位操作或某些log_2函数获得指数。但是,获取尾随二进制未设置位的数量是很棘手的。我不确定您可以或应该使用宏来做到这一点。

答:

1赞 Jonathan Leffler 10/25/2023 #1

参见 C11 §5.2.4.2.2 浮动类型的特征 <float.h>。您可能正在寻找 .请注意,标准中显示的数字是可接受的最小值 - 您的实现可能具有更高的值。DBL_DECIMAL_DIG

  • 十进制位数 n,使得任何具有 p 基数 b 位数的浮点数都可以四舍五入为具有 n 个十进制数字的浮点数,然后再次返回,而无需更改值,

    { p log10 b        if b is a power of 10
    {
    { [^1 + p log10 b^] otherwise
    

FLT_DECIMAL_DIG 6
DBL_DECIMAL_DIG 10
LDBL_DECIMAL_DIG 10

这可能不完全是你所追求的,但它是标准中最接近的近似值。

评论

0赞 Valeria Suarez 10/25/2023
就我而言,DBL_DECIMAL_DIG返回 17,但我发布的数字中有超过 17 位数字。在此之后的一段时间内,它被四舍五入,我正在尝试理解这种行为。
0赞 Jonathan Leffler 10/25/2023
只有 17 位数字可靠;在那之后,你正在处理噪音。查看我链接到的标准部分。可能还有其他事情告诉你你想知道。