2017-01-04 13 views
3

Мне нравится включать Python в мое исследование функций, однако я столкнулся с поведением, которое я не ожидал и не хотел для этих оценок.Как вычислить -1/(-343)^(1/3) как 1/7 в Python?

>>> def h(x): 
...  return -1/x**(1/3) 
... 
>>> h(-343) 
(-0.07142857142857145 + 0.12371791482634838j) 

Я хотел бы истинную обратную к следующей функции:

>>> def f(x): 
...  return x**3 
... 
>>> f(-7) 
-343 

Такой, что:

>>> def h(x): 
...  return -1/inverse_f(x) 
... 
>>> h(-343) 
0.14285714285714285 

Есть Pythonic способ получить такое поведение?

+0

Программисты Python обычно не используют 'lambda', когда функция будет вызываться по имени. Вы хотите определить именованные функции, такие как 'def h (x): return -1/x ** (1/3)'. – DyZ

+0

Благодарим вас за отзыв. Я изменил определения соответствующим образом. – Galen

+0

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

ответ

6

Вы получаете проблемы, потому что отрицательное число, возведенное в дробной степени может быть complex number.

Решение заключается в применении математической идентичности. Мы знаем, что если х отрицательно, то x 1/3 равно - ((- x) 1/3). Другими словами, мы превращаем x в положительное число, берем корень куба и снова отрицаем его. Вот код Python, чтобы сделать так:

def h(x): 
    if x >= 0: 
     return -1.0/x**(1.0/3.0) 
    else: # x < 0 
     return -h(-x) 

Чтобы объяснить, почему вы получаете эту проблему, в первую очередь, это помогает взглянуть на реализацию x**y (оператор питания). Ключевой математической идентичностью является то, что x y = exp (log (x) * y). Это тождество упрощает обработку полномочий, потому что экспонента обрабатывается как регулярное число и не нуждается в анализе (это целое число? Это доля? Отрицательно? И т. Д.).

Когда x - положительное число, log (x) - действительное число. Пока y также является действительным числом, exp (log (x) * y) будет действительным числом.

Но когда x является отрицательным числом, log (x) является комплексным числом. В частности, он равен log (-x) + pi * i. Когда мы умножим такое комплексное число на y, а затем применим exp(), результат будет обычно сложным числом, что вы не хотите.

1

Если вы хотите работать только в целых числах (и игнорировать сложные решения вашей функции), это может быть способ. по крайней мере, для вашего примера в заголовке он делает то, что вы хотите. (Так что это только адреса название вашего вопроса, а остальное изменилось теперь не поможет с этим ... Nayuki's answer будет)

gmpy2 имеет iroot метод:

import gmpy2 
print(gmpy2.iroot(343, 3)) # -> (mpz(7), True) 

начиная оттуда должны быть в состоянии объединить вашу функцию.

import gmpy2 
from fractions import Fraction 

def h(x): 
    sign = 1 if x >= 0 else -1 
    root, is_int = gmpy2.iroot(abs(x), 3) 
    if not is_int: 
     return None # the result is not an integer 
    root = int(root) 
    return -sign * Fraction(1, root) 

print(h(-343)) # -> 1/7 

и обратная:

def g(x): 
    return -Fraction(1, x**3) 

print(g(h(-343))) # -> -343 
+0

'iroot' не работает с отрицательными номерами. – DyZ

+0

@DYZ: именно это и есть 'sign' и' abs'! (о, ваш комментарий был, вероятно, до того, как я добавил полную функцию ...) –

+0

Отрицательное число имеет три кубических корня. Ваш код вычисляет только один из них. – DyZ