2017-02-12 17 views
3

Использование Python 3.5 как в repl.it, так и в консоли в Windows, я получаю неправильные ответы на корни куба.Неверное значение для корня куба в Python

Когда ввод (-1)**(1/3), Я получаю комплексное число (0.5000000000000001 + 0.8660254037844386j) в качестве ответа, когда оно должно быть просто -1. Любое отрицательное значение под этим корнем, кажется, дает сложный результат.

Я что-то не так?

+1

Почему это должно быть -1? –

+5

[Вы получаете правильный ответ] (http://math.stackexchange.com/questions/8760/what-are-the-three-cube-roots-of-1), но это всего лишь один из 3 возможных ответов. – roganjosh

+0

@omri_saadon, почему этого не должно быть? – Copperfield

ответ

1

Экспоненциальность с отрицательными основами обычно включает в себя сложные числа, поэтому Python переключается на сложные числа, когда видит отрицательную базу. Такое возведение в степень, как правило, неоднозначно, и Python не всегда возвращает значение, которое вы можете ожидать.

Для особого случая 1/3 мощности с реальными основаниями, вы могли бы написать такую ​​функцию:

def cubeRoot(x): 
    if x >= 0: 
     return x**(1/3) 
    else: 
     return -(-x)**(1/3) 

который даст ожидаемый корень реального куба.

+1

Изучив это больше, я, похоже, не могу найти метод, который возвращает вам все 3 в этом случае, просто возможность заставить реальное число, как вы это делаете в этом ответе. Вы знаете, существует ли такой метод? – roganjosh

+0

Например, я попробовал два метода из [здесь] (http://stackoverflow.com/questions/1361740/cubic-root-of-the-negative-number-on-python/1362288) и сообщается о реальном корне как '-1 + 1.2246467991473532e-16j'.Это только для моего собственного любопытства, не запрошенного OP. – roganjosh

+1

1/3 не представляется в виде числа с плавающей запятой, и поэтому существует гораздо больше трех значений (-1) ** x, где x - это самое близкое число с плавающей запятой до 1/3. –

0

Вы получаете именно этот ответ, потому что оператор мощности вычисляет

x**y = exp(y*ln(x)) 

и если x не является положительным вещественным, то ее логарифм вычисляется из основной ветви комплексного логарифма

ln(u+i*v)=0.5*ln(u²+v²) + i*arg(u+i*v) 

где в математических библиотечных терминах arg(u+i*v)=atan2(v,u).

Таким образом ln(-1)=i*pi и

(-1)**(1.0/3)=exp(i*pi/3)=cos(pi/3)+i*sin(pi/3) 

, который имеет значение, которое вы получили. Ошибки с плавающей запятой возникают, так как y=1.0/3 не точно 1/3, pi - это не точно математическая константа с тем же именем, а тригонометрические функции также являются приближениями к точным математическим функциям.

1

На самом деле, Python не знает, что вы берете корень куба!

Все, что он видит, является аргументом с плавающей запятой со значением, близким к 0.3333333333 ..., но из-за конечности представления невозможно предположить, что вы имеете в виду ровно 1/3.

Таким образом, все, что Python может сделать, это падать обратно на обычном определении экспоненциации отрицательных оснований к реальной мощности (основная ветвь), с помощью формулы

(-x)^y = exp(y(ln(x) + iπ) = exp(y ln(x)) (cos(yπ) + i sin(yπ)) 

, который дает комплексное значение.