面试题11:数值的整数次方
一.题目描述
实现函数double Power(double base,int exponent),求base得exponent次方。不得使用库函数,同时不需要考虑大数问题。
二.分析问题
1.解题思路
解法1
这道题因为不用考虑大数的问题,所以比较简单,但是我们不能因此掉以轻心,要将所有可能出现的情况考虑清楚。
- 如果指数为负数的时候,我们先对指数求绝对值,然后算出次方的结果之后再取倒数。
- 当底数是零且指数是负数的时候,如果不做特殊处理,就会出现对0求导数从而导致程序运行错误。
- 如果底数和指数其中任意一个为0,就返回1。
细节:
但我们在判断底数是不是等于0的时候,不能直接写 base == 0,这是因为在计算机内表示小数时(包括float和double型小数)都有误差。判断两个小数是否相等,只能判断他们之差的绝对值是不是在一个很小的范围内。如果两个数相差很小,就可以认为它们相等。
解法2
如果我们输入的指数exponent为32,在解法1中我们要循环31次乘法。但我们知道32是16的平方,而16次方是8的平方。以此类推,我们只需要知道它的2次方,接着再平方......我们只需要做5次乘法循环。
因此我们可以推导出以下公式:
三.代码
解法1
#include<stdio.h>
#include<stdlib.h>
bool equal(double a, double b)
{
if ((a - b > -0.0000001) && (a - b < 0.0000001))
{
return true;
}
else
{
return false;
}
}
double PowWithUnsigned(double base, unsigned int exponent)
{
double result = 1.0;
for (unsigned int i = 1; i <= exponent; ++i)
{
result *= base;
}
return result;
}
double Power(double base, int exponent)
{
if (equal(base, 0.0))//判断base是不是0
{
return 0.0;
}
if (exponent == 1)
{
return base;
}
if (exponent == 0)
{
return 1;
}
unsigned int abs_exponent = (unsigned int)exponent;
if (exponent < 0)
{
abs_exponent = (unsigned int)(-exponent);//如果指数小于0,则取它的绝对值
}
double result = PowWithUnsigned(base, abs_exponent);
if (exponent < 0)/*如果指数小于0,则取它的倒数*/
{
result = 1.0 / result;
}
return result;
}
int main()
{
double a = 2;
int b = 6;
printf("%lf\n", Power(a, b));
return 0;
}
运行结果:
解法2
#include<stdlib.h>
#include<stdio.h>
double PowerWithUnsignedExponent(double base, unsigned int exponent)
{
if (exponent == 0)
{
return 1;
}
if (exponent == 1)
{
return base;
}
double result = PowerWithUnsignedExponent(base, exponent >> 1);//右移一位相当于除以2
result *= result;
if ((exponent & 1) == 1)//判断是否为奇数
{
result *= base;
}
return result;
}
int main()
{
double a = 2;
int b = 6;
printf("%lf\n", PowerWithUnsignedExponent(-1,3));
return 0;
}
运行结果: