如何在恒定时间内仅使用算术运算计算指数?

Posted

技术标签:

【中文标题】如何在恒定时间内仅使用算术运算计算指数?【英文标题】:How to calculate exponent using only arithmetic operations in constant time? 【发布时间】:2020-09-13 12:59:09 【问题描述】:

我正在尝试找到一种方法来遍历大小为 N 的整数数组,并将这些整数中的每一个乘以 128^((N-1) - i),其中 N 是数组的长度,而 i是整数的索引,然后将所有这些结果加在一起。

例如,[1, 2, 3, 4] 的数组输入将返回 1 * (128^3) + 2 * (128^2) + 3 * (128^1) + 4 * (128^ 0).

我的算法需要在 O(N) 时间内运行,但指数运算很昂贵,例如,2^3 需要三个运算。所以,我需要找到一种方法来在 O(1) 时间内对数组中的每个整数进行运算,只使用算术运算(-、+、*、/、%)。我能想到的最明显(不正确)的方法是将每个整数(N-i)简单地相乘,但这并不需要恒定的时间。我也在考虑通过平方来使用求幂,但这需要 log_2(N-i) 时间来对每个整数进行运算,这不是恒定的。

【问题讨论】:

【参考方案1】:

128 是 2^7,将一个数字乘以 128^k 会将其二进制表示左移 7*k 个位置。

1 * (128^3) + 2 * (128^2) + 3 * (128^1) + 4 * (128^0)
= 1000000000000000000000 + 1000000000000000 + 110000000 + 100 

【讨论】:

【参考方案2】:

回答标题问题:有可能证明,在这些操作的数量不变的情况下,您无法使数字足够大以容纳足够大的指数。

要回答基本问题:您可以使用有时归因于霍纳的多项式评估方法:((1 * 128 + 2) * 128 + 3) * 128 + 4。请注意,除非您正在修改某些东西,否则操纵 bignums 仍然会花费您 Õ(n2) 时间。

如果您确实在使用 bignums,那么假设 bignum 乘法比学校方法运行得更快,那么有一个更复杂的分而治之的方法应该更快。这个想法是将输入分成两半,使用递归分别评估下半部分和上半部分,然后将它们放在一起。在您的示例中,这看起来像

(1 * 128 + 2) * 128^2 + (3 * 128 + 4),

我们通过重复平方计算术语128^2(即128^(n/2))。由于我们有循环,操作计数仍然是 O(n)

T(n) = 2 T(n/2) + O(log n),

属于Case 1。在实践中,无论特定实现具有何种渐近复杂度,大乘法都将控制运行时间。

【讨论】:

以上是关于如何在恒定时间内仅使用算术运算计算指数?的主要内容,如果未能解决你的问题,请参考以下文章

以太坊虚拟机介绍3-算术运算指令

C语言基础学习运算符-基本算术运算符

VBA算术运算符

C语言基础学习运算符-基本算术运算符

如何使用括号进行算术运算

4.1 算术运算和逻辑运算