仅需要k位时快速指数 - 续

时间:2013-07-06 20:36:01

标签: c++ algorithm math exponentiation

我需要帮助的地方......

我现在要做的是翻译此解决方案,该解决方案将数字的mantissa计算为c ++:

n^m = exp10(m log10(n)) = exp(q (m log(n)/q)) where q = log(10)

从结果中找到前n位数字可以这样做:

"the first K digits of exp10(x) = the first K digits of exp10(frac(x))
 where frac(x) = the fractional part of x = x - floor(x)."

我的尝试(由数学和this code引发)失败了......:

u l l function getPrefix(long double pow /*exponent*/, long double length /*length of prefix*/)
{
   long double dummy; //unused but necessary for modf
   long double q = log(10);

   u l l temp = floor(pow(10.0, exp(q * modf( (pow * log(2)/q), &dummy) + length - 1));
   return temp;
}

如果有人能够正确实施此解决方案,我需要你的帮助!!


修改

我尝试的输出示例:


n:2

m:0

n ^ m:1

计算的尾数:1.16334


n:2

m:1

n ^ m:2

计算的尾数:2.32667


n:2

m:2

n ^ m:4

计算的尾数:4.65335


n:2

m:98

n ^ m:3.16913e + 29

计算的尾数:8.0022


n:2

m:99

n ^ m:6.33825e + 29

计算的尾数:2.16596

1 个答案:

答案 0 :(得分:3)

我为此避免pow。众所周知,正确实施起来非常困难。有很多SO问题,人们在标准库中被错误的pow实现烧毁。

您还可以通过在自然基础而不是基础10中工作来节省大量的痛苦。您将获得如下代码:

long double foo = m * logl(n);
foo = fmodl(foo, logl(10.0)) + some_epsilon;
sprintf(some_string, "%.9Lf", expl(foo));
/* boring string parsing code here */

计算m log(n)的适当类比。请注意,可能出现的最大m * logl(n)2e10稍微大一点。当你将它除以2 64 并向上舍入到最接近的2的幂时,你会看到最差的foo的ulp是2 -29 。这尤其意味着,即使完美实现,使用long double也不能超过此方法的8位数。

some_epsilon将是最小long double,使expl(foo)始终超出数学上正确的结果;我还没准确计算出来,但它应该是1e-9的顺序。

鉴于这里的精确困难,我建议使用像MPFR这样的库来代替long double。您也可以使用double double技巧和四元精度explogfmod来获得一些效果。