2015-12-11 6 views
-1

я нашел следующий ответ здесь на Stackoverflow:Как рассчитать Python флоат-номер-й корень числа флоат

https://stackoverflow.com/a/356187/1829329

Но это работает только для целых чисел, как п в п-й корень:

import gmpy2 as gmpy 

result = gmpy.root((1/0.213), 31.5).real 
print('result:', result) 

результаты в:

--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-14-eb4628226deb> in <module>() 
     8 
----> 9 result = gmpy.root((1/0.213), 31.5).real 
    10 
    11 print('result:', result) 

TypeError: root() requires 'mpfr','int' arguments 

Что такое хороший и точный способ Calculat e такой корень? (Это питон кодовое представление некоторого формуляра, который мне нужно использовать для расчета в лекции.)

EDIT # 1

Вот мое решение, основанное на ответ Spektre «s и информации люди старше here at http://math.stackexchange.com.

import numpy as np 

def naive_root(nth, a, datatype=np.float128): 
    """This function can only calculate the nth root, if the operand a is positive.""" 
    logarithm = np.log2(a, dtype=datatype) 
    exponent = np.multiply(np.divide(1, nth, dtype=datatype), logarithm, dtype=datatype) 
    result = np.exp2(exponent, dtype=datatype) 
    return result 

def nth_root(nth, a, datatype=np.float128): 
    if a == 0: 
     print('operand is zero') 
     return 0 
    elif a > 0: 
     print('a > 0') 
     return naive_root(nth, a, datatype=datatype) 
    elif a < 0: 
     if a % 2 == 1: 
      print('a is odd') 
      return -naive_root(nth, np.abs(a)) 
     else: 
      print('a is even') 
      return naive_root(nth, np.abs(a)) 
+0

Когда a меньше 0 и вы берете нецелый корень, результатом является комплексное число. Функция 'nth_root' не делает этого. Я думаю, вы сделали его более сложным, чем нужно. – casevh

ответ

1

Power by squaring for negative exponents см

в любом случае, как я не код питона или gmpy некоторых определений первых:

  • pow(x,y) означает x питание от y
  • root(x,y) означает x его корня y

Поскольку эти обратные функции можно переписать:

  • pow(root(x,y),x)=y

equation

Вы можете использовать это, чтобы проверить на правильность. Поскольку функции обратные вы можете написать также следующее:

  • pow(x,1/y)=root(y,x)
  • root(1/x,y)=pow(y,x)

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

Кроме того, если вы получили, например, что-то вроде root(2/3,5) то вам нужно отделить целочисленные операнды первым:

root(2/3,5)=pow(root(2,5),3) 
~11.18034 = ~2.236068 ^3 
~11.18034 = ~11.18034 

Для irational корней и силы вы не можете получить точный результат. Вместо этого вы обходите корень или силу до ближайшего возможного представления, вы можете свести к минимуму ошибку или использовать подход pow(x,y) = exp2(y*log2(x)). Если вы используете десятичные числа с плавающей запятой или фиксированной точкой, вы можете забыть о точных результатах и ​​перейти с pow(x,y) = exp2(y*log2(x)) с самого начала ...

[Примечания]

Я предполагал только положительного операнд ... если вы получили отрицательное числа питания или корневой то вам необходимо обращаться знаком для целочисленных корней и степеней (чет/нечет) , Для илационные корни и силы имеют знак без значения (или, по крайней мере, мы пока не понимаем).

+0

Спасибо за знание математического фона. Является ли это плохая идея наивно (просто набрав то, что этот формуляр говорит в разделе «Деривация из метода Ньютона») реализует алгоритм Ньютона из https://en.wikipedia.org/wiki/Nth_root_algorithm, используя плавающие числа высокой точности? Если я правильно понимаю, он также может обрабатывать отрицательные корни, поэтому мне не придется обрабатывать знак, если я когда-либо хочу иметь отрицательный корень. – Zelphir

+0

@ Zelphir, это не очень хорошая идея (с моей точки зрения), поскольку корень может быть непосредственно вычислен за счет единственной мощности. В алгоритме Newtons вы используете iteartion через несколько вызовов мощности, увеличивая при этом погрешность аппроксимации по сравнению с прямым вычислением: 'root (x, y) = pow (y, 1/x) = exp2 (x * log2 (1/y)' ,, обрабатывать отрицательный 'y' просто вычислять с помощью' | y | 'и устанавливать результат на отрицательный, если' 1/y' или 'y' является нечетным (' y mod 2 == 1' или '1/y mod 2 == 1') функции 'exp2, log2' непосредственно реализованы на большинстве FPU, а также непосредственно вычислимы ... – Spektre

1

Если вы хотите использовать Python 3.x, родной pow() будет делать именно то, что вы хотите, просто используя root(x,y) = pow(x,1/y). Он автоматически вернет сложный результат, если это уместно.

Python 3.4.3 (default, Sep 27 2015, 20:37:11) 
[GCC 5.2.1 20150922] on linux 
Type "help", "copyright", "credits" or "license" for more information. 
>>> pow(1/0.213, 1/31.5) 
1.0503191465568489 
>>> pow(1/0.213, -1/31.5) 
0.952091565004975 
>>> pow(-1/0.213, -1/31.5) 
(0.9473604081457588-0.09479770688958634j) 
>>> pow(-1/0.213, 1/31.5) 
(1.045099874779588+0.10457801566102139j) 
>>> 

Возвращение сложного результата вместо воспитания ValueError является одним из изменений в Python 3. Если вы хотите, то же поведение с Python 2, вы можете использовать gmpy2 и дать комплексные результаты.

>>> import gmpy2 
>>> gmpy2.version() 
'2.0.5' 
>>> gmpy2.get_context().allow_complex=True 
>>> pow(1/gmpy2.mpfr("0.213"), 1/gmpy2.mpfr("31.5")) 
mpfr('1.0503191465568489') 
>>> pow(-1/gmpy2.mpfr("0.213"), 1/gmpy2.mpfr("31.5")) 
mpc('1.0450998747795881+0.1045780156610214j') 
>>> pow(-1/gmpy2.mpfr("0.213"), -1/gmpy2.mpfr("31.5")) 
mpc('0.94736040814575884-0.094797706889586358j') 
>>> pow(1/gmpy2.mpfr("0.213"), -1/gmpy2.mpfr("31.5")) 
mpfr('0.95209156500497505') 
>>> 
+0

Да, я ожидал большей потери точности при использовании' pow', возможно, я должен был пробовать этот путь Я уже обновил свой вопрос, чтобы содержать функцию, которую я написал для вычисления n-го корня. Я на самом деле всегда использую Python 3. Использует ли Python внутренние высокоскоростные библиотеки высокой точности для вычисления? Я использовал NumPy сейчас, с точностью float128, просто потому что я могу:) – Zelphir

+0

Я знаю, что есть gmpy2 на PyPi для Python 3, а также - наткнулся на некоторые сообщения на SO, которые вы написали во время моего поиска. Я не уверен, как NumPy работает внутри и как схож с gmpy2. Я тоже пробовал gmpy2 и не видел никакой разницы, за исключением того, что gmpy было немного сложнее читать (imo). – Zelphir

+1

'numpy' оптимизирован для работы с массивами/векторами типов, которые распознаются базовой аппаратной платформой. '128' в' float128' указывает объем памяти, используемый типом данных при хранении в массиве. Обычно это соответствует меньшему аппаратному типу. См. Http://stackoverflow.com/questions/9062562/what-is-the-internal-precision-of-numpy-float128. 'Gmpy2' выполняет вычисления с произвольной точностью и не полагается на собственные типы с плавающей запятой платформы. – casevh

0

Вот что-то я использую, что, кажется, работает с любым количеством просто отлично:

root = number**(1/nthroot) 
print(root) 

Он работает с любым типом количество данных.