计算 p^q(求幂)的有效方法,其中 q 是整数
Posted
技术标签:
【中文标题】计算 p^q(求幂)的有效方法,其中 q 是整数【英文标题】:Efficient way to compute p^q (exponentiation), where q is an integer 【发布时间】:2011-08-03 06:48:26 【问题描述】:计算 pq 的有效方法是什么,其中 q 是整数?
【问题讨论】:
【参考方案1】:假设^
表示求幂并且q
是运行时变量,请使用std::pow(double, int)
。
编辑:由于 cmets 对这个答案的完整性:我问了Why was std::pow(double, int) removed from C++11? 关于缺失函数的问题,实际上pow(double, int)
没有在 C++0x 中删除,只是语言发生了变化。但是,由于结果准确性问题,库似乎实际上并未对其进行优化。
即使我会仍然使用pow
,直到测量显示我需要对其进行优化。
【讨论】:
并假设 p 可以被强制为双精度。 @downvoter:这个解决方案有什么问题?当需要运行时可变性时,标准库可能具有高度优化的pow
函数。
其实我刚刚检查了我的 C++0x 草稿,std::pow(double,int) 没有定义。 std::pow(double,double) 和 std::pow(float,float) 以及一些更复杂的重载是。我认为这意味着 1)任何提供 std::pow(double,int) 的库都是非标准的,并且 2)如果它们在运行时执行特殊情况的整数值双精度数,那将是巨大的开销。因此,尽管我不是反对者,但我也会对此进行-1。
@Joe Wreschnig 我在 C++98 26.5/6 中发现了它,并假设它们不会删除 0x 中的功能。他们是否在 C++0x 中删除了它(我没有该标准的方便副本)?
@Mark B:我实际上无法在 Google 上快速找到 C++98 PDF,但在我的 C++0x PDF 中,唯一提到原始类型的 pow 是通过 26.8 中的 C99 嵌入,它只定义了 float、float、double、double 和 long double、long double 的 pow。【参考方案2】:
Exponentiation by squaring 仅使用 O(lg q) 乘法。
template <typename T>
T expt(T p, unsigned q)
T r(1);
while (q != 0)
if (q % 2 == 1) // q is odd
r *= p;
q--;
p *= p;
q /= 2;
return r;
这应该适用于任何monoid(T
,operator*
),其中从1
构造的T
是标识元素。这包括所有数字类型。
将其扩展到signed q
很容易:只需将1 除以上述结果即可得到q
的绝对值(但像往常一样,在计算绝对值时要小心)。
【讨论】:
我 -1d 这个因为它不是一个完整的答案;平方求幂是一个很好的算法,但也有其他问题。 @Joe:OP 要求的是建议,而不是完整的解决方案或正确性证明。 一般来说,我假设提出问题的人想要一个完整的解决方案。很少有人问到一半的答案。 投反对票真的有那么大的伤害吗?三个词的***链接中的 98 个代表真的那么少,你一定会感到不安,或者代表别人感到不安吗? @Joe Wreschnig:通常的投票标准(通过悬停在投票箭头上显示)是“这个答案有用吗”,而不是“这个答案是否尽可能完整”。另见meta.stackexchange.com/questions/2451/…【参考方案3】:我假设 ^ 你的意思是幂函数,而不是按位异或。
任何类型的 p 和任何正积分 q 的有效幂函数的开发是 an entire section, 3.2, in Stepanov's and McJones's book Elements of Programming 的主题。书中的语言不是C++,但很容易翻译成C++。
它涵盖了多项优化,包括通过平方求幂、转换为尾递归然后迭代和累积变量消除,并将优化与类型正则性和关联运算的概念联系起来,以证明它适用于所有此类类型。
【讨论】:
有趣的阅读:books.google.com/…以上是关于计算 p^q(求幂)的有效方法,其中 q 是整数的主要内容,如果未能解决你的问题,请参考以下文章