题目
面试题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;
}