题目:实现函数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一致;缺点:不能方便地使用计算结果。
全局变量 优点:能够方便地使用计算结果;缺点:用户可能会忘记检查全局变量。
异常 优点:可以为不同的出错原因定义不同异常类型,逻辑清晰明了;缺点:有些语言不支持异常,抛出异常时对性能由负面影响。
pow()函数自实现
于 2016-05-03 15:14:00 首次发布