You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SymPy矩阵科学计数法仅对小于1的值生效,applyfunc行为异常求解

问题

尝试用SymPy显示矩阵的科学计数法,但该功能仅对小于1的值生效。无法理解applyfunc为何表现出这种差异,请问是否有更好的实现方式?

代码示例

import numpy as np
from sympy import Matrix
from sympy.printing import latex
from IPython.display import display

C = np.array([
    [390, 145, ],
    [145, 0, ],
    ])*1e9

S_ij = np.linalg.inv(C)
S_scientific = Matrix(S_ij).applyfunc(lambda x: '{:.2e}'.format(float(x)))
print('this prints as desired:')
display(S_scientific) #m^2 / N 

def g(x):
    #shouldn't be necessary since 0 handles fine above
    if abs(float(x.evalf())) < 1e-10:
        return '0'
    else:
        return f'{float(x.evalf(8)):.2e}'
C_scientific = Matrix(C).applyfunc(g)
print()
print('this is not print in scientific notation:')
display(C_scientific) 
print(C_scientific)

输出情况

控制台输出


解决方案

问题原因

核心问题在于:当用applyfunc将矩阵元素转为格式化后的字符串时,SymPy Matrix会将这些字符串视为符号对象;而IPython的display在渲染时,会自动把可解析为数值的字符串转回数值类型。此时大数值会默认以普通十进制格式显示,而非科学计数法;而S_ij的元素是极小值,转回数值后IPython自动用科学计数法显示,所以看起来正常。

可行实现方式

方式1:自定义打印函数(简单可控)

直接遍历矩阵元素,按科学计数法格式化后打印,完全避开SymPy和IPython的自动渲染差异:

def print_matrix_scientific(mat):
    rows = []
    for row in mat.tolist():
        formatted_row = ['{:.2e}'.format(float(x)) for x in row]
        rows.append('[' + ', '.join(formatted_row) + ']')
    print('[' + '\n '.join(rows) + ']')

# 使用示例
print_matrix_scientific(Matrix(C))

方式2:自定义SymPy打印规则

通过继承SymPy的打印机类,修改数值的打印格式,让SymPy自身输出科学计数法:

from sympy import Float
from sympy.printing.str import StrPrinter

class ScientificStrPrinter(StrPrinter):
    def _print_Float(self, expr):
        return '{:.2e}'.format(float(expr))

def print_scientific(mat):
    printer = ScientificStrPrinter()
    print(printer.doprint(mat))

# 使用示例
print_scientific(Matrix(C))

方式3:Jupyter环境下的美观LaTeX显示

如果在Jupyter Notebook/Lab中使用,可生成科学计数法格式的LaTeX代码来显示:

from IPython.display import Math
import re

def display_matrix_scientific(mat):
    # 生成矩阵的LaTeX代码
    latex_str = latex(mat)
    # 将所有数值替换为科学计数法格式
    def replace_num(match):
        num = float(match.group(0))
        return '{:.2e}'.format(num)
    latex_str = re.sub(r'\d+\.?\d*(?:e[+-]?\d+)?', replace_num, latex_str)
    # 显示格式化后的矩阵
    display(Math(latex_str))

# 使用示例
display_matrix_scientific(Matrix(C))

总结

如果只需要控制台输出,方式1最简单直接;如果需要在Jupyter中美观显示,方式3更合适;方式2则适合需要全局修改SymPy打印行为的场景。

内容的提问来源于stack exchange,提问作者Erik Iverson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:24:55