在Python的 SymPy中使用UnevaluatedExpr时的显示问题

编程语言 2026-07-11

当我向Unevaluated() 添加另一个表达式后再尝试打印它时,未求值的输出会被括号包围。

问题出现在要在Unevaluated内显示的结果表达式的第一个系数为负数时,它会把首个(也是唯一的一个)负号放在整个表达式前面,挨着圆括号之前。

注:这不会影响后续计算,但确实会显示不正确的结果,因为此时我想要打印出其中的内容。

我折腾了一阵子,似乎没有一个很好的解决方案来解决这个问题。(例如使用自定义字符串处理、将其转换为LaTeX再转回等)

from sympy import symbols, simplify, UnevaluatedExpr, sstr, Eq, Add, S, latex
x, y = symbols('x y')
r1 = 0
r2 = -2
r3 = -9
uexpr = Add(S.One, UnevaluatedExpr(r1*x**3 + r2*x**2 + r3*x + 5))


print(f"Unevaluated: {uexpr}")
# Note the '-' in front of the parenthesis should not be applied to everything inside the parenthesis.
# Computationally, it doesn't get applied, this just seems to be a displaying error
# Output:
# Unevaluated: 1 - (2*x**2 - 9*x + 5)

print(f"Unevaluated: {uexpr.doit()}")
# Output:
# Unevaluated: -2*x**2 - 9*x + 6

下面是一些尝试解决此问题的其他示例,结果仍然显示不对(但在后端计算中是正确的)

ue1 = UnevaluatedExpr(-2*x**2 + 3*x + 2)
ue2 = UnevaluatedExpr(-5*x**2 + 6*x - 7)

print(f"ue1+ue2: {ue1+ue2}")
# ue1+ue2: -(5*x**2 + 6*x - 7) - (2*x**2 + 3*x + 2)

print(f"x * ue1+ue2: {x * ue1+ue2}")
# Note when multiplying by 'x' here that it shoves the '-' back into the () for the first expression.
# Just emphasizing that post-calculations work properly
# x * ue1+ue2: x*(-2*x**2 + 3*x + 2) - (5*x**2 + 6*x - 7)

print(f"Eq(simplify(ue1+ue2),y): {Eq(simplify(ue1+ue2),y)}")
# The simplified equation is correct as expected
# Eq(simplify(ue1+ue2),y): Eq(-7*x**2 + 9*x - 5, y)

print(f"sstr: {sstr(ue1+ue2)}")
# sstr: -(5*x**2 + 6*x - 7) - (2*x**2 + 3*x + 2)

print(f"LaTex: {latex(ue1+ue2)}")
# LaTex: - 5 x^{2} + 6 x - 7 + - 2 x^{2} + 3 x + 2

有哪些办法可以正确地打印这个?

# I want it to print either of the following
(-5*x**2 + 6*x - 7) + (-2*x**2 + 3*x + 2)
-5*x**2 + 6*x - 7 - 2*x**2 + 3*x + 2

# I do not want to print what I am currently getting:
-(5*x**2 + 6*x - 7) - (2*x**2 + 3*x + 2)

我当前的Sympy版本:

import sympy
print(f"version: {sympy.__version__}")
# output:
# version: 1.14.0

解决方案

这显然是/曾经是 UnevaluatedExpr() 中的一个bug。

>>> from sympy import *  # using SymPy 1.13.3 on test system
>>> from sympy.abc import x
>>> expr = Add(S.One, UnevaluatedExpr(-x - 5))
>>> expr                 # display bug you discovered
1 - (x - 5)
>>> expr.simplify()      # internal logic is not impacted
-x - 4

https://github.com/sympy/sympy/pull/29400 修复(comment)感谢 @Davide_sd,看来将包含在1.15版本的发行版中!

不过,你可以通过设置 evaluate=False 来避免 UnevaluatedExpr(),它对 Add() 以及其他基本运算符函数、sympify() 等也可用!

>>> e1 = -2*x**2 + 3*x + 2
>>> e2 = -5*x**2 + 6*x - 7
>>> Add(e1, e2)
-7*x**2 + 9*x - 5
>>> Add(e1, e2, evaluate=False)
(-5*x**2 + 6*x - 7) + (-2*x**2 + 3*x + 2)
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章