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
相关产品推荐
相关产品推荐

