C++ 仅需要k位时的快速求幂-续 我需要帮助的地方。。。

C++ 仅需要k位时的快速求幂-续 我需要帮助的地方。。。,c++,algorithm,math,exponentiation,C++,Algorithm,Math,Exponentiation,我现在要做的是将这个解决方案转换为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)." long

我现在要做的是将这个解决方案转换为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)."
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 */
我的尝试(由数学和数学引发)失败了…:

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

我会避免这一点。众所周知,很难正确实施。有很多这样的问题,人们被标准库中糟糕的
pow
实现烧死了

你也可以通过在自然基础上工作而不是在基础10上工作来避免很多痛苦。您将得到如下代码:

"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)."
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
。当你将其除以264并四舍五入到最接近的二次方时,你会发现
foo
的ulp在最坏情况下是2-29。这尤其意味着,使用
long double
s,即使使用完美的实现,也无法从该方法中获取超过8位的数据

一些ε
将是最小的
长双精度
,使得
expl(foo)
始终超过数学上正确的结果;我还没有精确地计算出来,但它应该在
1e-9
的顺序上


鉴于这里的精度困难,我可能建议使用类似MPFR的库,而不是
long double
s。您还可以使用
double-double
技巧和四精度
exp
log
,以及
fmod

定义“失败”。您能给出一些示例输入、您得到的输出和您期望的输出吗?也许这更适合于堆栈交换的数学部分。数学不是问题,而是将其转换为代码。如果这仍然适用于堆栈交换,我很乐意转移我的问题。我运行一个for循环,将循环的索引作为指数(pow)传递给函数,并将用户输入的变量作为所需的前缀长度(length)。我得到的是不是2的幂的数字的前缀(根据数学,应该硬编码到函数中)。我看不出哪里出了问题,所以我无法解释输出如何与输入相关。@Jonathan:你应该找到第一个得到错误结果的索引,然后将其作为一个独立的索引进行分解,我们可能会提供帮助。谢谢你的解释。我不会说谎。。。其中的一半对我来说还没有多大意义,但我会调查的!我注意到了精度问题。最后,我可能不得不找到另一种方法来解决我的问题。。。但说真的,再次谢谢你!另外,很抱歉,我无法给出您的答案……是否有任何可靠的方法来处理结果以
999999999999999
1000000000000000
开头的边缘情况?任意小的相对误差都可以改变结果。@zch:不。这种荒谬的小相对误差在这种情况下可能不会发生,但我没有一个严格的证据来证明原因。(加泰罗尼亚人猜想的最新证据表明,
999…9
从未出现过,尽管如此——这让我怀疑,在足够精确的情况下,要想找到比启发性论证更好的方法来解释这种黑客的工作原理,将是非常非常困难的。)