我有一个计算概率值的程序
(p-values),
但它正在输入一个非常大的负数
exp
功能
exp(-626294.830)
评估为零而不是非常小
它应该是正数。
如何将其评估为一个非常小的浮点数?
我试过了
Math::BigFloat
,
bignum
,和
bigrat
但都失败了。
答案 0 :(得分:6)
Wolfram Alpha说exp(-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()。