简体   繁体   English

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

[英]How to calculate exponent using only arithmetic operations in constant time?

I'm trying to find a way to loop through an array of integers of size N and multiply each of those integers by 128^((N-1) - i), where N is the length of the array and i is the index of the integer, and then adding all those results together.我试图找到一种方法来遍历大小为 N 的整数数组,并将这些整数中的每一个乘以 128^((N-1) - i),其中 N 是数组的长度,i 是索引的整数,然后将所有这些结果加在一起。

For example, an array input of [1, 2, 3, 4] would return 1 * (128^3) + 2 * (128^2) + 3 * (128^1) + 4 * (128^0).例如,[1, 2, 3, 4] 的数组输入将返回 1 * (128^3) + 2 * (128^2) + 3 * (128^1) + 4 * (128^0)。

My algorithm needs to run in O(N) time, but the exponent operation is expensive, as, for example, 2^3 takes three operations.我的算法需要在 O(N) 时间内运行,但指数运算很昂贵,例如,2^3 需要三个运算。 So, I need to find a way to operate on each integer in the array in O(1) time, using only arithmetic operations (-, +, *, /, %).所以,我需要找到一种方法来在 O(1) 时间内对数组中的每个整数进行运算,只使用算术运算(-、+、*、/、%)。 The most obvious (incorrect) way I could think of is simply multiplying each integer (Ni) times, but that does not take constant time.我能想到的最明显(不正确)的方法是简单地将每个整数 (Ni) 相乘,但这不需要常数时间。 I was also thinking of using exponentiation by squaring, but this takes log_2(Ni) time for operating on each integer, which is not constant.我也在考虑通过平方使用取幂,但这需要 log_2(Ni) 时间来操作每个整数,这不是常数。

128 is 2^7, and multiplying a number by 128^k shifts its binary representation left by 7*k positions. 128 是 2^7,将一个数乘以 128^k 会将其二进制表示向左移动 7*k 个位置。

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

To answer the title question: it's possible to prove that with a constant number of those operations, you can't make numbers big enough for sufficiently large exponents.回答标题问题:可以证明,使用恒定数量的这些操作,您不能使数字足够大以获取足够大的指数。

To answer the underlying question: you can use the polynomial evaluation method sometimes attributed to Horner: ((1 * 128 + 2) * 128 + 3) * 128 + 4 .要回答潜在的问题:您可以使用有时归因于霍纳的多项式评估方法: ((1 * 128 + 2) * 128 + 3) * 128 + 4 Note that unless you're modding by something, manipulating the bignums is still going to cost you Õ(n 2 ) time.请注意,除非您正在修改某些东西,否则操作 bignums 仍然会花费您 Õ(n 2 ) 时间。

If you are indeed working with bignums, there's a more complicated divide and conquer method that should be faster assuming that bignum multiplication runs faster than the school method.如果您确实在使用 bignum,那么假设 bignum 乘法比学校方法运行得更快,则有一种更复杂的分治法应该会更快。 The idea is to split the input in half, evaluate the lower and upper halves separately using recursion, and then put them together.这个想法是将输入分成两半,使用递归分别评估下半部分和上半部分,然后将它们放在一起。 On your example, this looks like在你的例子中,这看起来像

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

where we compute the term 128^2 (ie, 128^(n/2) ) by repeated squaring.我们通过重复平方计算术语128^2 (即128^(n/2) )。 The operation count is still O(n) since we have the recurrence操作次数仍然是 O(n) 因为我们有重复

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

which falls into Case 1 .这属于案例 1 In practice, the running time will be dominated by the large multiplications, with whatever asymptotic complexity the particular implementation has.在实践中,运行时间将由大乘法主导,无论特定实现具有何种渐近复杂度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM