大多数32位机器的指数限制是
exp( +/-700 )
但我想做一个指数计算
res = exp( x ) / exp( d )
当x或d大于700时,我使用的事实是
exp( x + y ) = exp( x ) . exp( y )
所以我的计算将是
res = (exp( x - z ).exp(z)) / (exp( d - z ).exp(z))
或
res = exp( x - z ) / exp( d - z )
其中(x-z)< 700
但是这种方法在某些情况下是有缺陷的,例如x = 6000和d = 10000的情况 如果我们使用z = 5300然后
res = exp( 6000 - 5300 ) / exp( 10000 - 5300 )
res = exp( 700 ) / exp( 47000 )
但是32位机器上的exp(47000)= 0。
如果我替换z = 9300,那我就会产生相反的效果。
res = exp( -3300 ) / exp( 700 )
那么考虑到计算机的局限性,我怎么能解决上面的等式,(我认为应该返回一个32位有效数字)?
修改 这样做的原因是我正在使用公式
P( a ) = P(y1) * P(y2) * P(y3) ... P(yN)
为了防止溢出,我做了
a = log( P(y1) ) + log( P(y2) ) + log (P(y3)) ... log( P(yN) )
b = log( P(z1) ) + log( P(z2) ) + log (P(z3)) ... log( P(zN) )
...
z = log( P(zz1) ) + log( P(zz2) ) + log (P(zz3)) ... log( P(zzN) )
得到我做的总数
total = a + b ... z
并计算我做的百分比
(exp(a) / exp( total ) ) * 100
但有可能" a"和/或"总计"大于700
我想问题可能是如何在不使用指数
的情况下计算百分比答案 0 :(得分:4)
答案 1 :(得分:2)
我假设您想要计算:
p = exp(a) / exp(b)
从a^b/a^c == a^(b-c)
开始,这会减少到
p = exp(a - b)
可以很容易地计算如果差异低于该临界指数。
如果不是,那么你的结果不能用像double
之类的原始数据类型来表示(因为它非常大或非常小),你需要某种任意精度数字,可能是由某些图书馆提供的。
但是如果您只需要打印结果或以某种方式存储它,那么您可以轻松计算甚至非常大的数字:
为此,您更改为基数10(用于显示),因此计算等效指数(tExponent = log10(eExponent)
),并将该值设置为std::numeric_limits::max_exponent10
和std::numeric_limits::min_exponent10
之间的允许范围,将差异保存为比例因子。
目前,我只有一个quick and dirty live example,显示
exp(90000) / exp(100) = 1.18556 scaled by 10^39043
注意:我写这篇文章的时候已经很晚了。我把它留在这里是为了另一种选择"方法的
现在,通常,有
a^b = [a^(b/c)]^c
从那以后
(a/b)^c = (a^c)/(b^c)
holds, too,我想这里最简单的方法是只要将两个指数分开,只要其中一个超过你的临界值,然后进行取幂,除以结果,最后使用前者的除数指数作为指数的指数:
double large_exp_quot(
double eNum,
double eDenom,
unsigned int const critical = 200) {
if (abs(eNum - eDenom) > critical) {
throw out_of_range{"That won't work, resulting exponent is too large"};
}
unsigned int eDivisor = 1;
while (abs(eNum) > critical or abs(eDenom) > critical) {
eNum /= 2;
eDenom /= 2;
eDivisor *= 2;
}
return pow(exp(eNum) / exp(eDenom), eDivisor);
}
但是这只会起作用,如果计算结果实际上可以使用C ++原始数据类型存储,在本例中为double
。您给出的示例...使用exponents 6000和10000 ...显然无法用double
表示(它e^(-4000)
因此非常小)
答案 2 :(得分:1)
数值不稳定的计算:exp(a)/ exp(b)
等效稳定计算:exp(a - b)
数值不稳定的计算:Π i = 1..n p i
等效稳定计算:exp(Σ i = 1..n log(p i ))