《剑指Offer》面试题:数值的整数次方

题目

面试题11:数值的整数次方
题目:实现函数double Power(double base,int exponent),
求base的exponent次方,不得使用库函数,同时不需要考虑大数问题

/*
面试题11:数值的整数次方 
题目:实现函数double Power(double base,int exponent), 
求base的exponent次方,不得使用库函数,同时不需要考虑大数问题
*/
/*需要考虑的测试用例如下
//base、exponent两者都不为零的情况 
 base=3 ,exponent=4//基数和指数均为正数
 base=-3,exponent=4//基数为负,指数为正
 base=3,exponent=-4//基数为正,指数为负
 base=-3,exponent=-4//基数、指数均为正
 //base、exponent至少有一个为零的情况 
 base=0,exponent=1
 base=0,exponent=-1//特别要注意 
 base=0,exponent=0 
*/


#include<stdio.h>
bool my_equal(double base,double num){
    if(base-num<0.0001&&base-num>-0.0001){
        return true;
    }
    return false;
}
//定义一个全局变量,来标志输入是否有效,当输入无效( base=0,exponent=-1//特别要注意 )的时候,该值为true 
bool  g_InvalidInput=false; 
 /*
 一般的思路如下 
 */
double  my_Power(double base,int exponent){
    g_InvalidInput=false;//初始化为false,目的是为了防止多次调用该函数,g_InvalidInput的标志位被设置为了true,对后面的调用的结果产生一定的影响 
    //先判断输入是否有效,即判断是否出现了 base=0,exponent=-1这种情况
    /*因为base为double型数据,因此不能直接用base==0来判断其是否等于0,
    这是因为计算机内表示小数时(包括float和double)都有一定的误差 ,
    因此判断两个小数是否相等,只能判断他们之差的绝对值是否在一定的范围内 */
    if(my_equal(base,0.0)&&exponent<0){
        g_InvalidInput=true;
        return 0.0;
    } 

    //将0的0次方单独拿出来考虑
    if(my_equal(base,0.0)&&exponent==0) {
        return 1.0;
    }
    double result=1.0;
    int negative=1;//指数是否为负数的标志位 
    if(exponent<0){
        negative=-1;
        exponent=-exponent; 
    }
    for(int i=0;i<exponent;i++){
        result*=base;
    }
   // printf("%lf\n",result);
   // printf("%lf\n",1.0/result);
    return (negative==1?result:(1.0/result));
} 


int main(void){
    double base;
    int exponent;
 //   scanf("%lf",&base);//这里注意的是:对于double类型的输入的格式为:“%lf” 
 //   scanf("%d",&exponent); 
 //   printf("%lf\n",Power(base,exponent));

    printf("%lf\n",my_Power(3.0,4));
    printf("%lf\n",my_Power(-3.0,4));
    printf("%lf\n",my_Power(3.0,-1));
    printf("%lf\n",my_Power(0.0,-1));
    printf("%lf\n",my_Power(0.0,1));
    printf("%lf\n",my_Power(0.0,0));
    return 0;
}

高效的改进

可能有人觉得当exponent有点大的时候,采用如下的for循环来计算数值的整数次方不高效

for(int i=0;i<exponent;i++){
        result*=base;
    }

于是,就有了如下的改进。

base的exponent次方
当exponent为偶数时等于base的(exponent/2)的平方
当exponent为奇数时等于base的(exponent/2)的平方再乘以一个base

实现代码如下:


#include<stdio.h>
//定义一个全局变量,来标志输入是否有效,当输入无效( base=0,exponent=-1//特别要注意 )的时候,该值为true 
bool  g_InvalidInput=false; 
bool my_equal(double base,double num){
    if(base-num<0.0001&&base-num>-0.0001){
        return true;
    }
    return false;
}

/*功能:更高效的完成数值的整数次方的运算 
比for(int i=0;i<exponent;i++){
        result*=base;
    }更高效 
@param base:基数
@param exponent:指数  且大于等于0 
*/
double PowerWithUnsiginedExponent(double base,int exponent){
    if(exponent==0){
        return 1.0;
    }
    if(exponent==1){
        return base;
    } 
    double result=PowerWithUnsiginedExponent(base,exponent>>1);
    result*=result;
    if(exponent&0x01){
        result*=base;
    }
    return result; 

}
double  my_Power(double base,int exponent){
    g_InvalidInput=false;//初始化为false,目的是为了防止多次调用该函数,g_InvalidInput的标志位被设置为了true,对后面的调用的结果产生一定的影响 
    //先判断输入是否有效,即判断是否出现了 base=0,exponent=-1这种情况
    /*因为base为double型数据,因此不能直接用base==0来判断其是否等于0,
    这是因为计算机内表示小数时(包括float和double)都有一定的误差 ,
    因此判断两个小数是否相等,只能判断他们之差的绝对值是否在一定的范围内 */
    if(my_equal(base,0.0)&&exponent<0){
        g_InvalidInput=true;
        return 0.0;
    } 

    //将0的0次方单独拿出来考虑
    if(my_equal(base,0.0)&&exponent==0) {
        return 1.0;
    }
    double result=1.0;
    int negative=1;//指数是否为负数的标志位 
    if(exponent<0){
        negative=-1;
        exponent=-exponent; 
    }
    result=PowerWithUnsiginedExponent( base, exponent);
   // printf("%lf\n",result);
   // printf("%lf\n",1.0/result);
    return (negative==1?result:(1.0/result));
} 


int main(void){
    double base;
    int exponent;
 //   scanf("%lf",&base);//这里注意的是:对于double类型的输入的格式为:“%lf” 
 //   scanf("%d",&exponent); 
 //   printf("%lf\n",Power(base,exponent));

    printf("%lf\n",my_Power(3.0,4));
    printf("%lf\n",my_Power(-3.0,4));
    printf("%lf\n",my_Power(3.0,-1));
    printf("%lf\n",my_Power(0.0,-1));
    printf("%lf\n",my_Power(0.0,1));
    printf("%lf\n",my_Power(0.0,0));
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值