面试题16:数值的整数次方
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0
常规方法:
当指数为正时,直接循环计算n次方即可;
当指数为0时,返回1;
当指数为负时,先对指数求绝对值,算出次方的结果之后再取倒数。这一步可以与第一步结合起来一起弄。
特别要注意的是:题目要求指数与底数不能同时为0。且,在数学上要求如0^-1等这种以0做底数的,指数不能小于0,所以也得满足这个要求。
代码:class Solution { public: const double doubleZero = 0.0000001; double Power(double base, int exponent) { //base与exponenet不同时为0;若base为0,则指数不能为负数 if ((base >= -doubleZero) && (base <= doubleZero) && exponent <= 0) { //cout << "input error!"<<endl; return NULL; } if (exponent == 0) return 1; double exponent_base=1.0; int exponent_positive = exponent; if (exponent < 0) exponent_positive = 0 - exponent; for (int i = 1; i <= exponent_positive; i++) { exponent_base = exponent_base * base; } if (exponent < 0) exponent_base = 1.0 / exponent_base; return exponent_base; } };
高级方法:
在常规方法中,当计算a^32次时需循环计算31次乘法。但若我们已经知道了a^16次,就能直接计算(a^16)^2得出最后结果,而a^16又是a^8的平方……依次考虑,得到公式
可以利用递归方法解决,具体代码如下:const double doubleZero = 0.0000001; double PowerWithUnsingedExponent(double base, unsigned int exponent); double Power(double base, int exponent) { //base与exponenet不同时为0;若base为0,则指数不能为负数 if ((base >= -doubleZero) && (base <= doubleZero) && exponent <= 0) { cout << "input error!"<<endl; return NULL; } if (exponent == 0) return 1; double exponent_base=1.0; unsigned int exponent_positive = (unsigned int)(exponent); if (exponent < 0) exponent_positive = (unsigned int)(- exponent); /* for (int i = 1; i <= exponent_positive; i++) { exponent_base = exponent_base * base; } */ exponent_base = PowerWithUnsingedExponent(base, exponent_positive); if (exponent < 0) exponent_base = 1.0 / exponent_base; return exponent_base; } //计算次方的具体方法。 double PowerWithUnsingedExponent(double base, unsigned int exponent) { if (exponent == 0) return 1; if (exponent == 1) return base; if (exponent % 2 == 0) { double halfResult = PowerWithUnsingedExponent(base , exponent/2); return halfResult * halfResult; } if (exponent % 2 == 1) { double halfResult = PowerWithUnsingedExponent(base , (exponent-1 / 2)); return halfResult * halfResult*base; } }
在代码中注意两点
- 由于我们在计算次方过程中一直将指数视为正数或0,所以可以直接将指数转化为unsigned int型变量;
- 书上实现的方法有两个细节:
用右移运算符>>代替了除以2;
用位与运算符&代替了求余运算符%来判断一个数是奇数还是偶数。
由于位运算符的效率比直接乘除法及求余运算的效率高很多,所以起到优化代码的作用。