Преобразуйте симпати поли с мнимыми способностями в mpmath mpc
У меня есть симпатичный поли, который выглядит так:
Poly(0.764635937801645*I**4 + 7.14650839258644*I**3 - 0.667712176660315*I**2 - 2.81663805543677*I - 0.623299856233272, I, domain='RR')
Я конвертирую в mpc используя следующий код:
a = val.subs('I',1.0j)
b = sy.re(a)
c = sy.im(a)
d = mpmath.mpc(b,c)
Два вопроса
- Предполагая, что мои mpc и sympy type имеют одинаковую точность (например, 100 dps), есть ли потеря точности при использовании этого преобразования из
a
вd
? - Есть ли лучший способ конвертировать?
В стороне: sympy, кажется, относится ко мне просто как к символу здесь. Как мне получить упрощение, чтобы упростить этот полином?
Редактировать: я также заметил, что следующие работы вместо a
выше:
a = val.args[0]
2 ответа
Строки и выражения
Коренная причина проблемы видна в val.subs('I', 1.0j)
- вы, кажется, передаете строки в качестве аргументов функциям SymPy. Для этого есть несколько допустимых применений (например, создание высокопрецизионных операций с плавающей точкой), но когда речь идет о символах, использование строк - это путаница. Строка 'I' неявно преобразуется в выражение SymPy Symbol('I')
, который отличается от выражения SymPy I
, Так что ответ на
Как мне получить упрощение, чтобы упростить этот полином?
это пересмотреть процесс создания этого полинома и исправить это. Если вам действительно нужно создать его из строки, используйте locals
параметр:
>>> S('3.3*I**2 + 2*I', locals={'I': I})
-3.3 + 2*I
Полиномы и выражения
Если структура Poly не нужна, используйте метод as_expr()
Поли, чтобы получить выражение от этого.
Преобразование в mpmath и потерю точности
есть ли потеря точности при использовании этого преобразования из a в d?
Да, расщепление на реальное и воображаемое, а затем рекомбинация может привести к потере точности. Передать объект SymPy напрямую mpc
если вы знаете, это сложное число. Или к mpmathify
если вы хотите, чтобы mpmath решил, какой тип он должен иметь. Пример:
>>> val = S('1.111111111111111111111111111111111111111111111111')*I**3 - 2
>>> val
-2 - 1.111111111111111111111111111111111111111111111111*I
>>> import mpmath
>>> mpmath.mp.dps = 40
>>> mpmath.mpc(val)
mpc(real='-2.0', imag='-1.111111111111111111111111111111111111111111')
>>> mpmath.mpmathify(val)
mpc(real='-2.0', imag='-1.111111111111111111111111111111111111111111')
>>> mpmath.mpc(re(val), im(val))
mpc(real='-2.0', imag='-1.111111111111111111111111111111111111111114')
Замечания:
- Когда я фактическая мнимая единица,
I**3
оценивает-I
Вам не нужно ничего делать, чтобы это произошло. - Строковое представление высокоточного десятичного числа используется для создания такого типа с плавающей точкой в SymPy. Вот
S
обозначаетsympify
, Можно также быть более прямым и использоватьFloat('1.1111111111111111111111111')
- Прямое преобразование комплексного числа SymPy в комплексное число mpmath предпочтительнее, чем расщепление в вещественное / сложное и рекомбинирование.
Заключение
Большинство из вышеперечисленных просто говорит о проблеме XY. Ваше выражение со мной было не таким, как вы думаете, поэтому вы пытались делать странные вещи, в которых не было необходимости, и мой ответ - в основном пустая трата времени.
Я добавляю здесь свой собственный ответ, так как ответ FTP, хотя и уместный и очень полезный, не (непосредственно) не решил мою проблему (что не было ясно из вопроса tbh). Когда я запустил код в его примере, я получил следующее:
>>> from sympy import *
>>> import mpmath
>>> val = S('1.111111111111111111111111111111111111111111111111')*I**3 - 2
>>> val
-2 - 1.111111111111111111111111111111111111111111111111*I
>>> mpmath.mp.dps = 40
>>> mpmath.mpc(val)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\mpmath\ctx_mp_python.py", line 373, in __new__
real = cls.context.mpf(real)
File "C:\Python27\lib\site-packages\mpmath\ctx_mp_python.py", line 77, in __new__
v._mpf_ = mpf_pos(cls.mpf_convert_arg(val, prec, rounding), prec, rounding)
File "C:\Python27\lib\site-packages\mpmath\ctx_mp_python.py", line 96, in mpf_convert_arg
raise TypeError("cannot create mpf from " + repr(x))
TypeError: cannot create mpf from -2 - 1.111111111111111111111111111111111111111111111111*I
>>> mpmath.mpmathify(val)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\mpmath\ctx_mp_python.py", line 662, in convert
return ctx._convert_fallback(x, strings)
File "C:\Python27\lib\site-packages\mpmath\ctx_mp.py", line 614, in _convert_fallback
raise TypeError("cannot create mpf from " + repr(x))
TypeError: cannot create mpf from -2 - 1.111111111111111111111111111111111111111111111111*I
>>> mpmath.mpc(re(val), im(val))
mpc(real='-2.0', imag='-1.111111111111111111111111111111111111111114')
>>> mpmath.mpmathify(val)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Python27\lib\site-packages\mpmath\ctx_mp_python.py", line 662, in convert
return ctx._convert_fallback(x, strings)
File "C:\Python27\lib\site-packages\mpmath\ctx_mp.py", line 614, in _convert_fallback
raise TypeError("cannot create mpf from " + repr(x))
TypeError: cannot create mpf from -2 - 1.111111111111111111111111111111111111111111111111*I
Обновление моих sympy (1.0->1.1.1) и mpmath (0.19->1.0.0) исправило исключения. Я не проверял, какое из этих обновлений действительно решило проблему.