一、题目描述
题目:数值的整数次方
实现函数 double Power(double base, int exponent),求 base 的 exponent 次方。不得使用库函数,同时不需要考虑大数问题。
二、解题思路
暂略。(此处主要作为书中python实现补充)
三、代码实现
题目中明确给出,不需要考虑大数问题,即不考虑溢出问题。不过,我们在这里还是需要考虑一些特殊情况。比如 b a s e base base 为0时, e x p o n e n t exponent exponent 为负数,此时若是采用先求出 b a s e base base 的 e x p o n e n t exponent exponent 的绝对值次方,即 r e s u l t = b a s e ∣ e x p o n e n t ∣ result = base^{|exponent|} result=base∣exponent∣,然后利用 r e s u l t = 1 / r e s u l t result = 1 / result result=1/result,就会出现 1/0 的情况,而导致出错。(当然题目给出 e x p o n e n t exponent exponent 为 i n t int int 类型,所以也不需要考虑指数为小数)
以下利用 python 代码简单实现了题目的要求,并针对特殊情况做了处理,具体如下:
def power(base, exponent):
if base == 0 and exponent < 0:
return False
result = 1.0
for i in range(abs(exponent)):
result = base * result
if exponent < 0:
result = 1.0 / result
return result
对上述代码进行简单的测试,如下。
>>> power(3, 3)
Out:
27.0
>>> power(0, 3)
Out:
0.0
>>> power(2, -2)
Out:
0.25
>>> power(0, -2)
Out:
False
在面试过程中,对代码做进一步优化,总是我们所追求的。例如,若 exponent 为 32,按照上面 power 函数的做法,for 循环中要进行31次乘法。若是换一种思路思考: b a s e 32 base^{32} base32 等于 b e s e 16 bese^{16} bese16 的二次方, b e s e 16 bese^{16} bese16 又是 b e s e 8 bese^{8} bese8 的二次方。以此类推,做 32 次方只需 5 次乘法,先求2次方,然后4次方,然后8次方,再然后16次方,最终求得32次方。
可以用以下公式来求 a 的 n 次方:
a n = { a n / 2 ⋅ a n / 2 n 为 偶 数 a ( n − 1 ) / 2 ⋅ a ( n − 1 ) / 2 ⋅ a n 为 奇 数 a^{n} = \left\{\begin{matrix} a^{n/2} \cdot a^{n/2} & n为偶数 \\ a^{(n-1)/2} \cdot a^{(n-1)/2} \cdot a & n为奇数 \end{matrix}\right. an={an/2⋅an/2a(n−1)/2⋅a(n−1)/2⋅an为偶数n为奇数
以上公式,其实很容易用递归实现,如下:
def powerAdvanced(base, exponent):
if base == 0 and exponent < 0:
return False
result = 1.0
# 将之前power函数中的for循环替换成以下递归函数
result = powerWithUnsignedExponent(base, abs(exponent))
if exponent < 0:
result = 1.0 / result
return result
# powerWithUnsignedExponent主要对无符号数求结果
def powerWithUnsignedExponent(base, exponent):
if exponent == 0:
return 1.0
elif exponent == 1:
return base
result = powerWithUnsignedExponent(base, exponent>>1)
result = result * result
if exponent & 0x1 ==1:
result = result*base
return result
这里对于普通用例的测试结果与前面一致,不再做演示。不过我们可以一起来看看两者运算效率的比较。
import time
time_start = time.time()
for i in range(10000):
power(1,10000)
time_end = time.time()
print("The total time of power is",time_end-time_start)
time_start = time.time()
for i in range(10000):
powerAdvanced(1,10000)
time_end = time.time()
print("The total time of powerAdvanced is",time_end-time_start)
Out:
The total time of power is 9.405900239944458
The total time of powerAdvanced is 0.06249380111694336
以上结果可明显看出,其运算效率确有很大提升。
扩展:当然,递归程序也可以进一步改写成循环实现,python 实现如下(仅供参考)。
def powerAdvancedBaseLoop(base, exponent):
if base == 0 and exponent < 0:
return False
result = powerWithUnsignedExponent(base, abs(exponent))
if exponent < 0:
result = 1.0 / result
return result
def powerWithUnsignedExponent(base, exponent):
temp = []
result = base
if exponent == 0:
return 1.0
elif exponent == 1:
return base
while exponent > 1:
temp.append(exponent)
exponent = exponent>>1
while len(temp):
temp_exponent = temp.pop()
result = result * result
if temp_exponent & 0x1 == 1:
result = result*base
return result
import time
time_start = time.time()
for i in range(10000):
powerAdvanced(1,10000)
time_end = time.time()
print("The total time of powerAdvanced is",time_end-time_start)
time_start = time.time()
for i in range(10000):
powerAdvancedBaseLoop(1,10000)
time_end = time.time()
print("The total time of powerAdvancedBaseLoop is",time_end-time_start)
The total time of powerAdvanced is 0.03191518783569336
The total time of powerAdvancedBaseLoop is 0.03393840789794922