python-3.x 使用SymPy计算黄金比率会产生复杂的结果

bxgwgixi  于 2023-02-26  发布在  Python
关注(0)|答案(2)|浏览(151)

我尝试使用SymPy构建一个正五边形,然后计算对角线与边的比率。这就是黄金分割率(1 + sqrt(5)) / 2,但SymPy计算不正确。SymPy的答案在手工简化后是黄金分割率与-i(负虚常数)的乘积-i * (1 + sqrt(5)) / 2

from sympy import simplify
from sympy.geometry import RegularPolygon, Point

sides = 5
polygon = RegularPolygon(Point(0, 0), 1, sides)
diagonal = polygon.vertices[0].distance(polygon.vertices[2])
print("Ratio:", simplify(diagonal/polygon.length))

Ratio: sqrt(sqrt(5) + 5)/sqrt(-sqrt(5) + 5)
我使用SymPy是因为我需要精确的值,并且在转移到其他多边形之前使用五边形作为测试用例。有没有方法可以确保SymPy避免给出复杂的解?

7kqas0il

7kqas0il1#

使用nsimplify而不是simplify可以修复此问题。

k2fxgqgv

k2fxgqgv2#

我之所以使用SymPy,是因为我需要精确的值
症状是针对symbolic mathematics的。如果你真的需要"精确值"到可用的精度,也许mpmath会更合适。
也就是说,Symy有工具来测试黄金分割率的近似值,在本例中,它是Expr. equals()函数:

from sympy import simplify
from sympy.geometry import RegularPolygon, Point
from sympy import GoldenRatio

sides = 5
polygon = RegularPolygon(Point(0, 0), 1, sides)
diagonal = polygon.vertices[0].distance(polygon.vertices[2])
print("Ratio:", simplify(diagonal/polygon.length))
print(simplify(diagonal/polygon.length).equals(GoldenRatio))
Ratio: sqrt(sqrt(5) + 5)/sqrt(5 - sqrt(5))
True

再说一次,这是符号数学,没有人有计算机能力,如果有的话,Python也没有精确比较无理数的能力。
例如:

>>> 1/3
0.3333333333333333
>>> 1/3 * 3
1.0
>>> 0.3333333333333333 * 3
1.0

CPython很难定义0.9~ == 1
所以这些比较是行不通的:

>>> from sympy import GoldenRatio, simplify
>>> simplify(diagonal/polygon.length) == GoldenRatio
False
>>> import math
>>> GoldenRatio.equals(math.sqrt(math.sqrt(5)+5)/math.sqrt(5-math.sqrt(5)))
False

另一个例子:

>>> from sympy import GoldenRatio, simplify
>>> simplify(diagonal/polygon.length) - GoldenRatio
-GoldenRatio + sqrt(sqrt(5) + 5)/sqrt(5 - sqrt(5))
>>> (simplify(diagonal/polygon.length) - GoldenRatio) == 0
False
>>> (simplify(diagonal/polygon.length) - GoldenRatio).equals(0)
True

我很抱歉,我无法避免这一点:simplify, man

相关问题