2013-11-22 56 views
1

我在leetcode中编写了一个简单问题的代码。它要求实施pow(x,n);它告诉我“运行时错误”,上次执行输入:1.00000,-2147483648。我改变了另一种方法,这是有效的。但我只是想知道我在做下面的代码中的错误。非常感谢!!我的电源功能实现有什么问题?

class Solution { 
public: 
    double pow(double x, int n) { 
     // IMPORTANT: Please reset any member data you declared, as 
     // the same Solution instance will be reused for each test case. 
     if(n==0 && x==0) return 1.0; 
     if(x==0) return 0; 
     if(n==0) return 1.0; 
     if(n<0) return 1/pow(x,-n); 
     if(n==1) return x; 

     double y=pow(x,n/2); 
     if(n%2==1) return y*y*x; 
     else return y*y; 

} 

};

+0

当该数字(' - ( - 2147483648)')不能用该数据类型表示时,您正在询问'-n'作为整数。结果是未定义的行为。在函数开始时测试'n'的大小。 – Floris

回答

6

假设int的长度是32位,-2147483648是一个唯一值,不是0,其中它的否定等于它自己。所以行:

if(n<0) return 1/pow(x,-n); 

使用相同的参数调用自己,并这样做,直到有堆栈溢出。

更详细地,的-2147483648二进制表示为:接着31个0小号

10000000000000000000000000000000 

1。根据two's complement采取否定是一个两步过程。 1)将所有0 s到1,反之亦然:

01111111111111111111111111111111 

然后2)添加1:

10000000000000000000000000000000 

所以我们得到相同的值。因此无限递归。

如果您必须处理这种情况,这里有一个想法。只是n<0测试之前插入此:

if (n==-2147483648) return 1/(x*pow(x,2147483647)); 

显然,这是此一例黑客攻击。最终,您的问题域将决定最优雅/一般的解决方案。

+0

表达式-n在这里实际上有未定义的行为。但是堆栈溢出是一种常见的观察行为,是的。 – aschepler

+0

非常感谢您的回复。我将它改为1/pow(x,abs(n));但它仍然不起作用。有任何想法吗? – user2994219

+1

'abs'不会让你的编译器更有能力把'1LL << 32'放入'int'中。你可以做一个特殊的案例测试。 – aschepler

2

-2147483648是十六进制80000000是最大的负数,并且比最大的正数多一个。所以当n = -2147483648时,没有-n。代码将失败

if(n<0) return 1/pow(x,-n); 

这当然是一个特例。

+0

*可能*失败。不要指望关于未定义行为的投诉。 – aschepler

+0

鉴于我们被告知代码失败,我认为我们不需要如此谨慎。我们可以假装成为程序员一次。 –

+0

我看到足够的关于“为什么没有这个不安全的代码失败/崩溃/错误”的stackoverflow问题对于使用任何指示性问题感到紧张。 – aschepler