pow()函数自实现

题目:实现函数double power(double base, int exponent),求base的exponent次方。不得使用库函数同时不需要考虑大数问题。

其实这道题就是要实现pow这个库函数。你可不要自以为这道题目简单,直接给出一个for循环了事。像下面这样:

double power(double base, int exponent)
{
	double result = 1.0;
	int i = 0;

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

	return result;
}

初看起来貌似没有问题,不过遗憾的是并没有考虑到所有的输入的情况。如果输入的指数小于1那怎么办?这段代码完全没有考虑这些意外!

同时,这段代码的效率高吗?不高。我们是否还有更好的解法,答案是肯定的!假设求a的n次方,当n为偶数时,a的n次方可以由两个a的n/2次方相乘求得;当n为奇数时,a的n次方可以由两个a的n/2次方相乘的积再乘以a得到。

由此,我们可以写出如下鲁棒又高效的代码:

int equal(double elem1, double elem2)
{
	if ((elem1 - elem2 < 0.0000001) && (elem1 - elem2 > -0.0000001))
		return 1;	//相等
	else
		return 0;	//不相等
}

double power_unsigned_exp(double base, unsigned int exponent)
{
	double result = 0.0;
	
	if (0 == exponent)
		return 1.0;
	if (1 == exponent)
		return base;

	result = power_unsigned_exp(base, exponent / 2);
	if (exponent & 1 == 1)
		result *= base;
	
	return result;
}

double power(double base, int exponent)
{
	unsigned int abs_exponent = exponent;
	double result = 0.0;
	invalid_input = 0;
	
	if (equal(base, 0.0) && exponent < 0)
	{
		invalid_input = 1;
		return 0.0;
	}

	if (exponent < 0)
		abs_exponent = (unsigned int)(-exponent);
	
	result = power_unsigned_exp(base, abs_exponent >> 1);
	result *= result;

	if (result < 0)
		result = 1.0 / result;
	
	return result;
}

这段代码中还有其它的优点。比如,要求exponent的一半是,使用了右移一位的操作,而不是简单的除以2,提升了效率;再比如,判断exponent的奇偶性是也是使用了位操作;还有,浮点数与浮点数的比较不能直接用==比较,牵扯到精度的问题。

最后一点,用了一个全局变量来标识是否出错。我们可以采用3种错误处理方法方法:返回值,全局代码和异常。这三种方法各有优缺点,需要自己权衡。下面简单的列出几种错误处理方式的优缺点:

返回值 优点:和系统API一致;缺点:不能方便地使用计算结果。

全局变量 优点:能够方便地使用计算结果;缺点:用户可能会忘记检查全局变量。

异常 优点:可以为不同的出错原因定义不同异常类型,逻辑清晰明了;缺点:有些语言不支持异常,抛出异常时对性能由负面影响。



你可能感兴趣的:(C语言)