sympy - UnevaluatedExpr и коммутативное свойство - оставьте число с плавающей точкой без оценки - PullRequest
1 голос
/ 04 февраля 2020

У меня есть следующее выражение: Bg = (pi / H)**2 + (2.405 / R)**2. В моих вычислениях я хотел бы оставить число с плавающей точкой 2.405 неоцененным, в противном случае я получаю длинные числа с плавающей точкой, разбросанные по всему выражению.

Я подумал, что мог бы использовать sympy UnevaluatedExpr для представления этого числа с плавающей точкой , Это хорошо сработало для дальнейшего развития моих выражений. Проблема заключается в том, что выражения, содержащие UnevaluatedExpr, не являются коммутативными, поэтому я не могу использовать такие методы, как solve(), factor(), collect(), ... в противном случае они выдают ошибки с жалобами на некоммутативный характер выражения.

Следующий код показывает, что выражение некоммутативно, потому что я использовал UnevaluatedExpr.

import sympy as sp
R, H = sp.symbols("R, H", real=True, positive=True)

Bg = (sp.pi / H)**2 + (sp.UnevaluatedExpr(2.405) / R)**2
print(Bg)
print(Bg.is_commutative)

>>> 2.405**2/R**2 + pi**2/H**2
>>> False

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

Bg = (sp.pi / H)**2 + (2.405 / R)**2
print(Bg)
print(Bg.is_commutative)

>>> 5.784025/R**2 + pi**2/H**2
>>> True

Вопросы:

  1. Может ли UnevaluatedExpr и коммутативное поведение быть ошибкой?
  2. Какой лучший способ справиться с числом с плавающей запятой и предотвратить их оценку? Я думал о замене числа символом: это хорошо для моего простого примера, но если я буду работать с большими выражениями, это может быстро превратиться в беспорядок.

1 Ответ

1 голос
/ 06 февраля 2020

Да, я бы посчитал это ошибкой. Я бы предложил открыть вопрос об этом https://github.com/sympy/sympy/issues/new.

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

class UnevaluatedFloat(Expr):
    def __new__(cls, arg):
        return Expr.__new__(cls, Float(arg))

    def _eval_evalf(self, prec):
        return self.args[0]._eval_evalf(prec)

    def _sympystr(self, printer):
        return printer.doprint(self.args[0])

. Это создаст класс, который выдает число с плавающей запятой при вызове evalf, но в противном случае остается без оценки. Это также печатает как плавание. Я добавил принтер str, но вы также можете определить другие методы печати, которые вам нужны, например, _pretty, _latex и так далее. Поиск "printmethod" в https://docs.sympy.org/latest/modules/printing.html.

Пример

>>> UnevaluatedFloat(1.0) + 1
1 + 1.0
>>> (UnevaluatedFloat(1.0) + 1).evalf()
2.00000000000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...