前言:
此时看官们对“python的math函数库求和”大约比较着重,咱们都想要知道一些“python的math函数库求和”的相关文章。那么小编在网络上搜集了一些有关“python的math函数库求和””的相关知识,希望我们能喜欢,小伙伴们快快来了解一下吧!在当下 AI 迅猛发展的时期,Python 凭借其简洁易读的语法以及强大的表现力,深受程序员与科学家的青睐。本文旨在展示 Python 仅用 10 行代码便能完成复杂数学运算的强大能力,涵盖向量加法、点积、矩阵乘法、矩阵转置以及线性系统求解器等诸多方面。
回想最初使用 Python 时,NumPy 或 SymPy 尚未出现。那时,研究常借助 MatLab,快速原型设计依赖 Delphi……甚至还会在 Prolog 中进行符号计算。那时的 Python 类似优化版的 Perl,但并非研究人员的首选。
不过,用它编写程序颇具趣味,我因而选择以 Python 来实现论文中的部分实验,其中涉及一些线性代数的内容。起初,我采用类似 Pascal 风格的嵌套循环程序,感觉较为枯燥,然而随着对 Python 研究的深入,有趣的一面逐渐展现。
某一时刻,我察觉到这门语言绝非仅能编写嵌套循环,于是开始更深入地探索,而非局限于论文所需——这或许是我所做的最佳“错误”决定。
Python 以其友好的学习曲线著称,但这也可能带来问题。您可以用 Python 编写类似 Pascal、C++ 或 Lisp 的程序,但只有以 Python 特有的方式编写,方能充分发挥其优势。
好在,即便仅掌握 Python 的基础知识,可能会错失精彩部分,但用户体验依然良好。
为阐释这一点,我选取了线性代数领域。按理说,Python 有众多出色的库可处理线性代数,因此无需重新实现文中提及的内容。而我选择线性代数,旨在证明 Python 中以少量代码表达丰富含义的语法是完全可行的(免责声明:为保证可读性,部分代码示例未严格限制在一行内,示例中的所有缩进纯粹是为了提升阅读体验)。
列表解析
列表解析是 Python 单行代码的精髓所在,它是一种用于描述列表转换的特殊语法。例如,若要将一个向量乘以一个标量,在类似 Pascal 的 Python 代码中,可能会这样书写:
def scaled(A, x): B = list() for i in range(len(A)): B.append( A[i] * x ) return B
这种写法虽无过错,也有其优点,例如总能找到一行设置断点,但确实显得有些“冗长”。在 Python 中,您可以简洁地写成:
def scaled(A, x): return [ai*x for ai in A]
然后其运行效果如下:
List comprehension [1.0, 4.0, 3.0]* 2.0 [,...Step 1 [1.0, 4.0, 3.0] * 2.0 [2.0,...Step 2 [1.0, 4.0, 3.0] * 2.0 [2.0, 8.0,...Step 3 [1.0, 4.0, 3.0] * 2.0 [2.0, 8.0, 6.0]
不过,列表解析并非 Python 所独有,Haskell 和 Clojure 也具备类似功能,甚至 C# 的 LINQ 也为范围提供了特殊语法。鲜为人知的是,Python 还支持字典解析和元组解析。
>>> [2*v for v in [1.0, 2.0, 3.0]][2.0, 4.0, 6.0]>>> {k:2*v for k, v in {0:1.0, 1:4.0, 2:3.0}.items()}{0: 2.0, 1: 8.0, 2: 6.0}>>> tuple(2*v for v in (1.0, 4.0, 3.0))(2.0, 8.0, 6.0)
列表压缩
列表压缩能够将多个可迭代对象作为一个整体进行迭代,并将所有对象转换为一个元组列表。尽管标题提及“列表”,但它同样适用于元组、字典、生成器等任何可迭代的对象。
>>> A = [1, 2, 3]>>> B = ('a', 'b', 'c')>>> C = {1:'a', 2:'b', 3:'c'}>>> D = xrange(123)>>> zip(A, B, C, D)[(1, 'a', 1, 0), (2, 'b', 2, 1), (3, 'c', 3, 2)]
同样,您可以用一行代码实现向量加法。
def sum_of(A, B): return [ai+bi for (ai, bi) in zip(A, B)]
对于两组列表,这能够如同拉链一般将数据压缩在一起。
List zipping A = [1.0, 4.0, 3.0] B = [7.0, 3.0, 1.0]zip(A, B) = [...Step 1 A = [1.0, 4.0, 3.0] B = [7.0, 3.0, 1.0]zip(A, B) = [(1.0, 7.0),...Step 2 A = [1.0, 4.0, 3.0] B = [7.0, 3.0, 1.0]zip(A, B) = [(1.0, 7.0), (4.0, 3.0),...Step 3 A = [1.0, 4.0, 3.0] B = [7.0, 3.0, 1.0]zip(A, B) = [(1.0, 7.0), (4.0, 3.0), (3.0, 1.0)]
求和函数
求和函数能够进行简单的求和操作。您可以通过累积向量元素的乘积,用一行代码实现向量点积。
def dot_of(A, B): return sum([ai*bi for (ai, bi) in zip(A, B)])
然而,有时简单的求和并不足够。例如在处理浮点数时,可能会遭遇一些恼人的小误差。为了更加便利,Python 提供了另一个求和函数,能够对部分求和进行操作,从而获取更精确的输出。
>>> [0.1]*10[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]>>> sum([0.1]*10)0.9999999999999999>>> import math>>> math.fsum([0.1]*10)1.0
条件表达式
条件表达式是 Python 中的三元运算符,是依赖于条件的表达式,通常也是简单纯粹的表达式。我们能够用条件表达式来构建一个单位矩阵。
def identity(n): return [[1.0 if i==j else 0.0 for j in range(n)] for i in range(n)]
这实际上是一个包含条件表达式的嵌套列表解析,结果如下:
Conditional expression: 0 == 0 j = 0[[1.0,... i = 0Conditional expression: 1!= 0 j = 1[[1.0, 0.0,... i = 0Conditional expression: 2!= 0 j = 2[[1.0, 0.0, 0.0],... i = 0Conditional expression: 0!= 1 j = 0[[1.0, 0.0, 0.0], [0.0,... i = 1Conditional expression: 1 == 1 j = 1[[1.0, 0.0, 0.0], [0.0, 1.0,... i = 1Conditional expression: 2!= 1 j = 2[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0],... i = 1Conditional expression: 0!= 2 j = 0[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0,... i = 2Conditional expression: 1!= 2 j = 1[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0,... i = 2Conditional expression: 2 == 2 j = 2[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] i = 2
条件表达式在简洁性和表达力方面表现出色,但由于它们是表达式,所以不易添加副作用。但并非完全不可能,只是需要一些技巧。在 Python 中,元组计算会从左到右依次计算每个元组元素,所以当您需要在表达式中添加更多内容时,只需使用元组即可。
def identity(n): return [[1.0 if i==j else (0.0, sys.stdout.write("i!= j\n") )[0] for j in range(n)] for i in range(n)]
您也不能在表达式中使用 print,因为它们不应具有副作用,但可以使用 sys.stdout.write。
def identity(n): return [[1.0 if i==j else (0.0, sys.stdout.write("i!= j\n") )[0] for j in range(n)] for i in range(n)]
同样的技巧也适用于 lambda 表达式,您可以通过元组让您的 lambda 表达式尽可能复杂。不过建议若非必要,请勿如此操作。
我猜测肯定会有人反驳说,“您的例子根本无需条件表达式!”的确如此。在 Python 中,您可以显式地将布尔类型变量转换为浮点数变量。
def identity(n): return [[float(i==j) for j in range(n)] for i in range(n)]
这只是风格问题。就个人而言,我更倾向于将事实和数字分开,不这样做也完全可行。
将容器内容作为参数传递
假设在 Python 中我们有一个矩阵,以列表形式表示,其中每个嵌套列表是一行。若将这些行传递给前面提到的 zip,它会生成一个元组列表,其中每个元组代表矩阵的一列。如此一来,我们便得到了一个现成的矩阵转置。
不过,我们还需解决两个问题。一个较为简单:我们期望矩阵是一个列表,而非元组,所以需要通过一个简单的列表解析来解决。另一个问题则需使用特殊的 Python 语法,它能让我们将列表转变为函数参数的元组,此语法便是在矩阵前添加一个星号。
def transposed(A): return [list(aj) for aj in zip(*A)]
领取方式:私信回复666,免费领取资料软件~
标签: #python的math函数库求和