如何从 mpfr_get_prec() 返回的值计算DECIMAL_DIG?

How to compute DECIMAL_DIG from value returned by mpfr_get_prec()?

提问人:pmor 提问时间:9/11/2023 最后编辑:pmor 更新时间:9/13/2023 访问量:57

问:

上下文:C 标准具有宏,可用于保持浮点值的精度。示例:xxx_DECIMAL_DIGprintfdouble

printf("%.*g\n", DBL_DECIMAL_DIG, x); 

一个简单的问题:如何计算 从 返回的值的相似值?DECIMAL_DIGmpfr_get_prec

例:

#include <stdio.h>
#include <mpfr.h>

#define PREC 128

int prec2decimal_dig(int prec)
{
    return prec / 3;    // example, not accurate
}

int main (void)
{
    mpfr_t x;

    mpfr_init2(x, PREC);
    mpfr_set_d(x, 2.0 / 3.0, MPFR_RNDN);
    mpfr_printf("%.*Rf\n", prec2decimal_dig(PREC), x);
    return 0;
}

$ gcc t78a.c -lmpfr -lgmp -oa && ./a
0.666666666666666629659232512494781985878944

究竟是怎么回事?prec2decimal_dig


额外:base-2:为什么DECIMAL_DIG - DIG == 2 或 3?

浮点 精度 MPFR

评论


答:

1赞 chux - Reinstate Monica 9/11/2023 #1

XXX_DECIMAL_DIG来源于:

  • “b”,基数。示例:2、10、...

  • 'p',显式或隐式编码的位数(以基数为单位)。b

什么时候是 10 的幂:b

XXX_DECIMAL_DIG = p * log10(b)

否则

XXX_DECIMAL_DIG = ceiling(1 + (p * log10(b)))

将 28/93 用于略大于对数102 的分数。

常见示例double

DBL_DECIMAL_DIG = (int) ceil(1 + (53 * log10(2));
DBL_DECIMAL_DIG = (int) ceil(1 + (53 * 28.0/93));
DBL_DECIMAL_DIG = 1 + ((53 * 28 + 92)/93);
DBL_DECIMAL_DIG = 17;

#define LOG10_2_NUM 28
#define LOG10_2_DEN 93
int prec2decimal_dig(int prec) {
  return 1 + ((prec*28 + 92)/93);
  // or 
  return (prec*LOG10_2_NUM + LOG10_2_DEN*2 - 1)/LOG10_2_DEN;
}
2赞 vinc17 9/13/2023 #2

在实践中,原生浮点数几乎总是在基数 2 中(即 = 2 和 b = 2 在 C 标准中的描述),就像 MPFR 一样。在这种情况下,您可以使用基数 b = 10(请注意,C 标准中的 b 是输入基数,即 2,MPFR 手册中的 b 是输出基数,即本上下文中的 10)。此函数描述如下:FLT_RADIXDECIMAL_DIGmpfr_get_str_ndigits

返回最小整数 m,这样,当输出的 m 位在基数 b 中,四舍五入到最接近时,任何数量的 p 位都可以在再次读取时准确恢复,仍然四舍五入到最接近。更准确地说,我们有 m = 1 + ceil(p × log(2)/log(b)),如果 b 是 2 的幂,则 p 替换为 p − 1。

请注意,如果 = 10 在您的平台上,只是 p。而且我不知道任何其他带有另一个基数的平台。FLT_RADIXDECIMAL_DIG

评论

0赞 pmor 9/19/2023
在此程序中,x 为非零,但打印值为零。为什么?怎么修?
0赞 vinc17 9/20/2023
@pmor 您需要使用格式说明符,而不是 .gf
0赞 pmor 9/20/2023
还行。转换说明符有什么解决方案吗?f
0赞 vinc17 9/20/2023
@pmor 请注意,如果考虑转换说明符,则与(即使与本机 C 浮点类型)无关。此外,所需的精度显然取决于数量。一个简单的解决方案可能是计算以 10 为基数的第一个非零数字的指数;然后计算使用此值所需的精度和 。但获得的精度可能不是最佳的。fDECIMAL_DIGfmpfr_get_str_ndigits
0赞 pmor 9/22/2023
谢谢!我必须学习更多(C23 已过时)和.我已经问了原生 FP 类型的相关问题DECIMAL_DIG%g