sympy 如何处理 0.5 次方的指数?

Idi*_*ieh 3 python floating-point sympy

((gamma-(gamma**2-omega**2)**0.5)*(gamma+(gamma**2-omega**2)**0.5)).simplify()
Run Code Online (Sandbox Code Playgroud)

输出为:gamma^2 - (gamma^2 -omega^2)^{1.0} $

然而,我预计结果是 omega^2。我知道在 sympy 文档中,它警告要小心浮点数,但我的印象是整数和 2 的小数次幂(可以精确表示)都很好。

以下代码正确地再现了 omega^2:

((gamma-(gamma**2-omega**2)**sym.Rational(1,2))*(gamma+(gamma**2-omega**2)**sym.Rational(1,2))).simplify()
Run Code Online (Sandbox Code Playgroud)

为什么第一个代码没有产生预期的结果?

Osc*_*min 6

SymPy 认为精确数和不精确数之间存在区别。在这种情况下, float 像0.51.0被认为是不精确的,因此不清楚是否x**1.0真的等于x或等于稍微不同的东西,比如 say x**1.00000000000000000000001。这是因为浮点数通常由浮点计算产生,可能存在舍入误差。在您的示例中,结果是:

\n
In [5]: from sympy import *\n\nIn [6]: gamma, omega = symbols('gamma, omega')\n\nIn [7]: e = ((gamma-(gamma**2-omega**2)**0.5)*(gamma+(gamma**2-omega**2)**0.5)).simplify()\n\nIn [8]: e\nOut[8]: \n              1.0\n 2   \xe2\x8e\x9b 2    2\xe2\x8e\x9e   \n\xce\xb3  - \xe2\x8e\x9d\xce\xb3  - \xcf\x89 \xe2\x8e\xa0 \n
Run Code Online (Sandbox Code Playgroud)\n

如果你想告诉 SymPy 应该1.0被视为精确的,1那么你可以使用 SymPy 的nsimplify函数:

\n
In [9]: nsimplify(e)\nOut[9]: \n 2\n\xcf\x89 \n
Run Code Online (Sandbox Code Playgroud)\n

  • 关键是 SymPy 通常会拒绝将“可能”不精确的结果简化为“看起来”像精确结果的结果。一旦使用了浮点数,表达式就会受到不精确的影响,并且应该保持这种状态,无论像“0.5”或“1.0”这样的特定数字是否可以精确地表示为浮点数。每个浮点数都可以精确地表示为浮点数,但如果它是由浮点运算产生的,那么它的值可能不是这些运算的真正精确结果。 (2认同)