python 在SymPy中打印舍入到3位小数的输出

bvn4nwqk  于 2023-01-08  发布在  Python
关注(0)|答案(4)|浏览(201)

我得到一个SymPy矩阵M

In [1]: from sympy import *
In [2]: M = 1/10**6 * Matrix(([1, 10, 100], [1000, 10000, 100000]))
In [3]: M
Out[3]: 
Matrix([
[1.0e-6, 1.0e-5, 0.0001],
[ 0.001,   0.01,    0.1]])

我想打印舍入到3位小数的输出,如下所示:

In [3]: M
Out[3]: 
Matrix([
[ 0.000, 0.000, 0.000],
[ 0.001, 0.010, 0.100]])

在普通Python中,我会这样做:

In [5]: '{:.3f}'.format(1/10**6)
Out[5]: '0.000'

但是在SymPy矩阵中怎么做呢?
此外,更常见的情况是表达式还包含符号

x = symbols('x')
M = 1/10**6 * Matrix(([1, 10*x, 100], [1000, 10000*x, 100000]))

首选输出为

In [3]: M
Out[3]: 
Matrix([
[ 0.000, 0.000*x, 0.000],
[ 0.001, 0.010*x, 0.100]])
laawzig2

laawzig21#

要对表达式中的每个数字进行四舍五入,请使用以下函数

def round_expr(expr, num_digits):
    return expr.xreplace({n : round(n, num_digits) for n in expr.atoms(Number)})

它可以应用于任何SymPy表达式,包括矩阵。

x = symbols('x')
M = 1/10**6 * Matrix(([1, 10*x, 100], [1000, 10000*x, 100000]))
round_expr(M, 3)

收益率

Matrix([
[  0.0,      0, 0.0],
[0.001, 0.01*x, 0.1]])

对于数值矩阵,下面的表达式比较简单,并且保留尾随零:

>>> M.applyfunc(lambda x: Symbol('{:.3f}'.format(x)))
Matrix([
[0.000, 0.000, 0.000],
[0.001, 0.010, 0.100]])

在这里,applyfunc将给定的函数应用于M的每一个条目。自然的尝试是lambda x: '{:.3f}'.format(x),但SymPy矩阵并不真正意味着保存字符串:字符串将被解析回数字,并删除尾随零,从而导致

Matrix([
[  0.0,  0.0, 0.0],
[0.001, 0.01, 0.1]])

所以我把每个字符串都 Package 在Symbol中,这样就产生了一个新的符号,符号可以出现在矩阵中,并打印为它们的名称,在本例中名称是“0.000”等等。

esyap4oy

esyap4oy2#

我需要改进这2个解决方案(Space47已经改进了公认的解决方案),因为我的数字非常大,而Symy只发送“123456789.123 x”

def printM(expr, num_digits):
     return expr.xreplace({n.evalf() : n if type(n)==int else Float(n, num_digits) for n in expr.atoms(Number)})

因此,“123456789.123 x”将显示为1.23 * 10^8,并且该函数不会更改整数的表示(之前,“1”被“1.0”替换)

fslejnso

fslejnso3#

有点老了,但我今天花了一些时间才找到这个问题,需要一些调整。我对完全相同的问题的解决方案与前面的答案(user6655984)相同,但使用了evalf():

def printM(expr, num_digits):
    return expr.xreplace({n.evalf() : round(n, num_digits) for n in expr.atoms(Number)})

那么,例如sqrt(13)仍然是sqrt(13),而不是一个数值。(否则,在舍入之后,它被转换成一个数值,从而具有比num_digits更多的位数。至少在Python 3.7.1的Symy 1.3中是这样)

w46czmvw

w46czmvw4#

我有一些代码包含许多print('some string', some_sympy_expression)形式的指令,所以我使用了the function by 2diabolos.com(命名为round_expr),定义了下面的函数,并将每个print替换为print_my

def print_my(*args, **kwargs):
    end_my = kwargs['end'] if 'end' in kwargs else '\n'
    sep_my = kwargs['sep'] if 'sep' in kwargs else ' '
    for arg in args:
        if (type(arg)==str):
            print(arg, end=sep_my)
        else:
            print(round_expr(arg, 3), end=sep_my)
    print(end=end_my)
    return

我没有花时间检查是否有其他用例需要进行一些修改才能使其工作,或者甚至有其他用例不能使用这种方法。

相关问题