2013-11-22 3 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

Вы запрашиваете '-n' как целое число, когда это число (' - (- 2147483648) ') не может быть представлено в этом типе данных. Результатом является неопределенное поведение. Проверьте размер 'n' в начале функции. – Floris

ответ

6

Предполагая, что int имеет длину 32 бита, -2147483648 - единственное уникальное значение, отличное от 0, в котором его отрицание равно самому себе. Таким образом, линия:

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

вызывает себя с теми же параметрами и делает это до тех пор, пока не произойдет переполнение стека.

Более подробно, двоичное представление -2147483648 является:

10000000000000000000000000000000 

Это 1 следуют 31 0 с. Взятие отрицания в соответствии с two's complement является двухэтапным процессом. 1) Измените все 0 с до 1 и наоборот:

01111111111111111111111111111111 

затем 2) добавить 1:

10000000000000000000000000000000 

Таким образом, мы получаем обратно то же значение. Отсюда бесконечная рекурсия.

Если вы ДОЛЖНЫ обрабатывать этот случай, вот одна идея. Вставьте этот раз перед испытанием n<0:

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

Очевидно, что это хак для этого одного случая. В конечном итоге ваша проблемная область определит самое элегантное/общее решение.

+0

Выражение '-n' на самом деле имеет Undefined Behavior здесь. Но переполнение стека является обычным наблюдаемым поведением, да. – aschepler

+0

Большое вам спасибо за быстрый и приятный ответ. Я изменил его на 1/pow (x, abs (n)); Но это все еще не работает. Есть идеи? – user2994219

+1

'abs' не делает ваш компилятор более способным помещать' 1LL << 32' в 'int'. Вы можете сделать специальный тест. – aschepler

2

-2147483648 is hex 80000000 - наибольшее отрицательное число, и один больше, чем наибольший положительный. Поэтому, когда n = -2147483648, нет -n. Код не будет завершен на линии

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

Это, конечно, особый случай.

+0

* возможно * неисправность. Не рассчитывайте на жалобы о неопределенном поведении. – aschepler

+0

Учитывая, что нам говорят, что код не работает, я не думаю, что мы должны быть осторожны. Мы можем просто притворяться программистами на этот раз. –

+0

Я вижу достаточно вопросов stackoverflow о том, «почему этот небезопасный код не прошел/сбой/ошибка», чтобы нервничать относительно использования каких-либо индикативных. – aschepler

Смежные вопросы