数值收敛和最小数量

时间:2018-02-10 17:37:07

标签: perl floating-point precision

我有一个计算概率值的程序 (p-values), 但它正在输入一个非常大的负数 exp功能 exp(-626294.830)评估为零而不是非常小 它应该是正数。

如何将其评估为一个非常小的浮点数? 我试过了 Math::BigFloatbignum,和 bigrat 但都失败了。

2 个答案:

答案 0 :(得分:6)

Wolfram Alphaexp(-626294.830)是4.08589×10 ^ -271997 ...零与;-)非常接近虽然你已经编辑并从你的问题中删除了上下文,你真的需要使用这么小的数字,或者你可以通过某种方式优化你的算法或扩展你的数字吗?

无论如何,即使在Math::BigFloat->new("-626294.830")->bexp的支持下,像use Math::BigFloat lib => 'GMP';这样的代码似乎需要相当长的时间才是正确的。

我现在可以提供的唯一替代方案是Math::Prime::Util::GMP's expreal,但您需要为其指定精确度。

use Math::Prime::Util::GMP qw/expreal/;
use Math::BigFloat;
my $e = Math::BigFloat->new(expreal(-626294.830,272000));
print $e->bnstr,"\n";
__END__
4.086e-271997

但是在我的机器上,即使仍然需要大约20秒才能运行,这让我们回到了其他地方潜在优化的问题。

答案 1 :(得分:4)

浮点数不具有无限精度。假设该数字表示为IEEE 754双精度,我们对于一个分数有52位,对于指数有11位,对于符号有一位。由于指数的编码方式,可以表示的最小正数是2 ^ -1022。

如果我们查看你的数字e ^ -626294.830,我们可以做一个基数的变化,看它等于2 ^(log_2 e·-626294.830)= 2 ^ -903552.445,这明显小于2 ^ -1022 。因此,将您的数字近似为零是正确的。

不是使用任意精度数值来计算这个值,而是用手来解决必要的方程,然后以不需要极高精度的方式对其进行编码。例如,您不太可能需要e ^ -626294.830的确切值,但可能只是幅度。然后,您可以计算对数而不是使用exp()。