剑指Offer--第16题 数值的整数次方
第16题 数值的整数次方
题目:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
思路 看到有点懵,第一感觉觉得是不是应该考虑0的0次或者负数情况,还有就是浮点类型没办法使用"="号,最后自己以偷懒的方式直接调用Java的API,如果面试题中不让调用库函数,那么基本上这题就是挂了可能。
以上题目描述来自牛客,没有对使用做限制。真正的剑指offer上有限制条件不得使用库函数,同时不需要考虑大数问题。
自己的low代码
public class Solution {
public double Power(double base, int exponent) {
return Math.pow(base, exponent);
}
}
剑指offer思路::需要将所有情况考虑全面:base可为正、0和负,同样exponent也可以为正、0和负。1、当base为0,exponent为负时,这是一种常见的异常,分为为0异常;2、当exponent为0时;3、expoonent为负;4、考虑运行效率问题;
结果正确,但效率不高的写法:
public class Solution {
public double Power(double base, int exponent) {
if(base==0&&exponent<0) {
return 0;
}
if(exponent==0) { //这样判断是合理的;
return 1;
}
int ex = exponent;
if(exponent<0){ //容易忽略;
ex = -exponent;
}
double result = 1;
for(int i=0;i<ex;i++ ) { //效率不高;
result *= base;
}
if(exponent<0) {
result=1/result;
}
return result;
}
}
问题:除了使用for循环外,还有就是double为0等号的使用,之前一直有一个错觉就是浮点类型不能使用等号判断,因为不准确,所以对这种写法第一反应就是不正确。但是看了看了网上的解释发现,其实这种写法有道理的,因为
回复于 2013-11-27 09:55:46 #5 得分:5
首先一个 double 是否为 0,或者其他的数值,是精确的,可以使用== 。
比如 double f = 0; 此时 f 是精确为 0 ,f == 0 为 true。
但是,double 在运算中,由于截尾的原因,总是有误差的。而此时是否为0,要看你的这个运算的精度要求。
比如运算后,f = 0.001,此时不能简单去和 e 去比较。
简单来说,就是如果你所要比较的那个值如果是精确的那么比较就是精确的,如果本身存在截取,那么使用就不正确。
对for循环进行改进
public class Solution {
public double Power(double base, int exponent) {
if(base==0&&exponent<0) {
return 0;
}
int ex = exponent;
if(exponent<1){
ex = -exponent;
}
double result = Power3(base,ex);
if(exponent<0) {
result=1/result;
}
return result;
}
public double Power3(double base, int exponent) {
if(exponent ==0 ) {
return 1;
}
if(exponent==1) {
return base;
}
double result = Power3(base,exponent>>1);
result *=result;
if((exponent&1)==1) {//奇偶判断
result *=base;
}
return result;
}
}
优雅写法
链接:https://www.nowcoder.com/questionTerminal/1a834e5e3e1a4b7ba251417554e07c00
来源:牛客网
/**
* 1.全面考察指数的正负、底数是否为零等情况。
* 2.写出指数的二进制表达,例如13表达为二进制1101。
* 3.举例:10^1101 = 10^0001*10^0100*10^1000。
* 4.通过&1和>>1来逐位读取1101,为1时将该位代表的乘数累乘到最终结果。
*/
public double Power(double base, int n) {
double res = 1,curr = base;
int exponent;
if(n>0){
exponent = n;
}else if(n<0){
if(base==0)
throw new RuntimeException("分母不能为0");
exponent = -n;
}else{// n==0
return 1;// 0的0次方
}
while(exponent!=0){
if((exponent&1)==1)
res*=curr;
curr*=curr;// 翻倍
exponent>>=1;// 右移一位
}
return n>=0?res:(1/res);
}
多思考,多尝试。