为负指数产生错误结果的 power to n 实现
Power to n implementation that produces wrong results for negative exponent
在 pow(x, n)
方法的以下(天真)实现中,完全忽略任何优化方法,我发现以下问题:
public double pow(double x, int n) {
boolean negative = n < 0;
long power = Math.abs(n);
double ans = 1.0;
for(long i = 0; i < power; i++) {
ans = ans * x;
}
return negative ? 1.0/ans: ans;
}
这里我假设对于负指数的情况我简单地计算 x^n
然后 return 1/(x^n)
因为例如2^(-3) = 1/(2^3)
问题:
代码在以下情况下失败:
pow(2.00000, -2147483648)
输出是 1.00000
而预期的正确结果是 0.00000
如果我改代码如下:
public double pow(double x, int n) {
long power = n;
if(power < 0) {
x = 1 / x;
power = -power;
}
double ans = 1.0;
for(long i = 0; i < power; i++) {
ans = ans * x;
}
return ans;
}
结果正确!
那么做这些方法有什么区别呢?我原以为它们是等效的,但它们不是
Math.abs(n)
还是一个int
,后来才赋给了一个long
,所以-2147483648
的绝对值是-2147483648
再次(这在 the documentation of Math.abs(int)
中注明)。对于负边界,循环不执行迭代。
Math.abs((long)n)
可以解决这个问题。
在 pow(x, n)
方法的以下(天真)实现中,完全忽略任何优化方法,我发现以下问题:
public double pow(double x, int n) {
boolean negative = n < 0;
long power = Math.abs(n);
double ans = 1.0;
for(long i = 0; i < power; i++) {
ans = ans * x;
}
return negative ? 1.0/ans: ans;
}
这里我假设对于负指数的情况我简单地计算 x^n
然后 return 1/(x^n)
因为例如2^(-3) = 1/(2^3)
问题:
代码在以下情况下失败:
pow(2.00000, -2147483648)
输出是 1.00000
而预期的正确结果是 0.00000
如果我改代码如下:
public double pow(double x, int n) {
long power = n;
if(power < 0) {
x = 1 / x;
power = -power;
}
double ans = 1.0;
for(long i = 0; i < power; i++) {
ans = ans * x;
}
return ans;
}
结果正确!
那么做这些方法有什么区别呢?我原以为它们是等效的,但它们不是
Math.abs(n)
还是一个int
,后来才赋给了一个long
,所以-2147483648
的绝对值是-2147483648
再次(这在 the documentation of Math.abs(int)
中注明)。对于负边界,循环不执行迭代。
Math.abs((long)n)
可以解决这个问题。