提问人:pmor 提问时间:9/11/2023 最后编辑:pmor 更新时间:9/13/2023 访问量:57
如何从 mpfr_get_prec() 返回的值计算DECIMAL_DIG?
How to compute DECIMAL_DIG from value returned by mpfr_get_prec()?
问:
上下文:C 标准具有宏,可用于保持浮点值的精度
。示例:xxx_DECIMAL_DIG
printf
double
printf("%.*g\n", DBL_DECIMAL_DIG, x);
一个简单的问题:如何计算 从 返回的值的相似值?DECIMAL_DIG
mpfr_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
答:
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_RADIX
DECIMAL_DIG
mpfr_get_str_ndigits
返回最小整数 m,这样,当输出的 m 位在基数 b 中,四舍五入到最接近时,任何数量的 p 位都可以在再次读取时准确恢复,仍然四舍五入到最接近。更准确地说,我们有 m = 1 + ceil(p × log(2)/log(b)),如果 b 是 2 的幂,则 p 替换为 p − 1。
请注意,如果 = 10 在您的平台上,只是 p。而且我不知道任何其他带有另一个基数的平台。FLT_RADIX
DECIMAL_DIG
评论
0赞
pmor
9/19/2023
在此程序中,x 为非零,但打印值为零。为什么?怎么修?
0赞
vinc17
9/20/2023
@pmor 您需要使用格式说明符,而不是 .g
f
0赞
pmor
9/20/2023
还行。转换说明符有什么解决方案吗?f
0赞
vinc17
9/20/2023
@pmor 请注意,如果考虑转换说明符,则与(即使与本机 C 浮点类型)无关。此外,所需的精度显然取决于数量。一个简单的解决方案可能是计算以 10 为基数的第一个非零数字的指数;然后计算使用此值所需的精度和 。但获得的精度可能不是最佳的。f
DECIMAL_DIG
f
mpfr_get_str_ndigits
评论