如何解决是否有一种非黑客方法可以在 SymPy 中使用整数打印连分数而不进行评估?
我想用 SymPy
以那种形式显示带整数的连分数,但我似乎无法让 SymPy
遵守。我发现 this Stack Overflow 问题和答案非常有用(见下文),但在这里无法达到我的目标:
这是 $\frac{13}{5}$ 的连续分数展开。这种扩展的一个常见符号是只给出框内的术语,如下面的 SymPy
,即 SymPy
continued_fraction_iterator
中的 $[2,1,2]$:>
Rat_13_5 = list(continued_fraction_iterator(Rational(13,5)))
print( Rat_13_5 )
Rat_13_5 = list(continued_fraction_iterator(Rational(13,5)))
( Rat_13_5 )
print( Rat_13_5 )
输出 [2,2]
。
Sympy 手册版本 1.5 2019 年 12 月 9 日的第 37 页提供了一个代码片段来打印这样一个扩展的分数列表:
def list_to_frac(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr += i
expr = 1/expr
return l[0] + expr
如果您使用 list_to_frac
连分数扩展列表调用 Rat_13_5
,SymPy
会启动并计算它:
print( list_to_frac( Rat_13_5 ) )
输出 13/5
如果您使用符号列表,则 list_to_frac
打印所需的连分数,例如,
n1,n2,n3,n4,n5,n6,n7,n8,n9 = symbols('n1:10')
cont_frac_list = [n2,n1,n2]
contfrac12201015 = list_to_frac( [n2,n2] )
contfrac122010154
产生所需的结果(我在 JupyterLab 环境中工作,因此实际上我在整个过程中都获得了 typset LaTeX 输出):
n2 + 1/(n1 + 1/(n1 + 1/n2))
我重写了 list_to_frac
以使用 Francesco 在我之前引用的 StackOverflow 问题中提供的 UnevaluatedExpr
工具:
def list_to_frac_noEval(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr = UnevaluatedExpr(expr + i)
expr = UnevaluatedExpr( 1/expr )
return l[0] + expr
在 $\frac{13}{5}$ 扩展列表上调用 list_to_frac_noEval
:
list_to_frac_noEval( [2,2] )
我获得输出
2 + (1 + (1 + 2**(-1))**(-1))**(-1)
有些人使用这种符号(所以我想在任何情况下分享 list_to_frac_noEval
,如果你想看到连分数,那比以一个评估的单一有理数结束更好),例如 Roger Penrose in section $\unicode{x00A7}3.2$ The Road to Reality (2004),但我仍然觉得很烦人,当使用整数而不是符号时,我无法获得显式连分数格式。
我尝试用整数代替符号 evaluate=False
,同时使用 subs
方法和 Subs
函数,研究了 sympify
和 {{1 }} 和 srepr
与 parse_expr
,,但无法说服 evaluate=False
打印我使用 SymPy 1.4
对符号参数进行操作获得的显式分数形式。有没有办法在不修改 list_to_frac
代码或特殊大小写一组特定数字的情况下实现这一点?
解决方法
您可以将 evaluate=False
显式传递到表达式树的每个部分来构造表达式:
def list_to_frac(l):
expr = Integer(0)
for i in reversed(l[1:]):
expr = Add(i,expr,evaluate=False)
expr = Pow(expr,-1,evaluate=False)
return Add(l[0],evaluate=False)
这给出:
In [2]: nums = list(continued_fraction_iterator(Rational(13,5)))
In [3]: nums
Out[3]: [2,1,2]
In [4]: list_to_frac(nums)
Out[4]:
1
───────────── + 2
1
───────── + 1
1
───── + 1
0 + 2
看起来这是错误的方式,但这只是使用默认设置进行打印的方式:
In [5]: init_printing(order='old')
In [6]: list_to_frac(nums)
Out[6]:
1
2 + ─────────────
1
1 + ─────────
1
1 + ─────
0 + 2
您可以使用 doit
触发评估:
In [7]: _.doit()
Out[7]: 13/5
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。