NumPy¶
NumPy最初不会导入到SAGE中。要使用NumPy,您首先需要导入它。
sage: import numpy
NumPy中的基本计算对象是数组。创建数组很简单。
sage: l = numpy.array([1,2,3])
sage: l
array([1, 2, 3])
NumPy数组可以存储任何类型的Python对象。然而,为了速度,数值类型被自动转换为本机硬件类型(即, int
, float
等)如果可能的话。如果本地硬件类型无法处理数字的值或精度,则将创建Sage对象数组。您可以对这些数组进行计算,但它们可能比使用本机类型慢。当NumPy数组包含Sage或Python对象时,数据类型被显式打印为 object
。如果在NumPy打印数组时没有显式显示数据类型,则类型为硬件浮点型或整型。
sage: l = numpy.array([2**40, 3**40, 4**40])
sage: l
array([1099511627776, 12157665459056928801, 1208925819614629174706176], dtype=object)
sage: a = 2.0000000000000000001
sage: a.prec() # higher precision than hardware floating point numbers
67
sage: numpy.array([a,2*a,3*a])
array([2.000000000000000000, 4.000000000000000000, 6.000000000000000000], dtype=object)
这个 dtype
属性告诉您数组的类型。对于快速的数值计算,您通常希望它是某种浮点数。如果数据类型为Float,则数组存储为机器浮点数的数组,这样占用的空间少得多,操作速度也快得多。
sage: l = numpy.array([1.0, 2.0, 3.0])
sage: l.dtype
dtype('float64')
属性,可以创建特定类型的数组 dtype
参数。如果要确保处理的是机器浮点,最好指定 dtype=float
在创建数组时。
sage: l = numpy.array([1,2,3], dtype=float)
sage: l.dtype
dtype('float64')
您可以像访问任何列表一样访问NumPy数组的元素,也可以获取切片
sage: l = numpy.array(range(10),dtype=float)
sage: l[3]
3.0
sage: l[3:6]
array([3., 4., 5.])
你可以做基本的算术运算
sage: l+l
array([ 0., 2., 4., 6., 8., 10., 12., 14., 16., 18.])
sage: 2.5*l
array([ 0. , 2.5, 5. , 7.5, 10. , 12.5, 15. , 17.5, 20. , 22.5])
请注意 l*l
将使元素乘以 l
组件方面。要获得点积,请使用 numpy.dot()
。
sage: l*l
array([ 0., 1., 4., 9., 16., 25., 36., 49., 64., 81.])
sage: numpy.dot(l,l)
285.0
我们还可以创建二维数组
sage: m = numpy.array([[1,2],[3,4]])
sage: m
array([[1, 2],
[3, 4]])
sage: m[1,1]
4
这基本上等同于以下内容
sage: m = numpy.matrix([[1,2],[3,4]])
sage: m
matrix([[1, 2],
[3, 4]])
sage: m[0,1]
2
不同之处在于, numpy.array()
, m
仅被视为数据数组。特别是 m*m
将按组件方式相乘,但是使用 numpy.matrix()
, m*m
会做矩阵乘法。我们还可以做矩阵向量乘法和矩阵加法
sage: n = numpy.matrix([[1,2],[3,4]],dtype=float)
sage: v = numpy.array([[1],[2]],dtype=float)
sage: n*v
matrix([[ 5.],
[11.]])
sage: n+n
matrix([[2., 4.],
[6., 8.]])
如果 n
是用 numpy.array()
,然后要执行矩阵向量乘法,您可以使用 numpy.dot(n,v)
。
所有NumPy数组都有一个形状属性。这是一个可操作的有用属性
sage: n = numpy.array(range(25),dtype=float)
sage: n
array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.,
11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21.,
22., 23., 24.])
sage: n.shape=(5,5)
sage: n
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[10., 11., 12., 13., 14.],
[15., 16., 17., 18., 19.],
[20., 21., 22., 23., 24.]])
这会将一维数组更改为 5times 5 数组。
NumPy数组也可以切片
sage: n = numpy.array(range(25),dtype=float)
sage: n.shape = (5,5)
sage: n[2:4,1:3]
array([[11., 12.],
[16., 17.]])
需要注意的是,分片矩阵是对原始矩阵的引用
sage: m = n[2:4,1:3]
sage: m[0,0] = 100
sage: n
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 100., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
您将注意到原始矩阵已更改。这可能是你想要的,也可能不是。如果您想更改切片矩阵而不更改原始矩阵,则应复制一份
m=n[2:4,1:3].copy()
一些特别有用的命令有
sage: x = numpy.arange(0,2,.1,dtype=float)
sage: x
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2,
1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9])
你可以看到 numpy.arange()
创建一个从0到2递增0.1的浮点数数组。 numpy.r_()
这最好用例子来解释。
sage: from numpy import r_
sage: j = complex(0,1)
sage: RealNumber = float
sage: Integer = int
sage: n = r_[0.0:5.0]
sage: n
array([0., 1., 2., 3., 4.])
sage: n = r_[0.0:5.0, [0.0]*5]
sage: n
array([0., 1., 2., 3., 4., 0., 0., 0., 0., 0.])
numpy.r_()
提供高效构造NumPy数组的快捷方式。上面的注解 0.0:5.0
是对以下的速记 0.0, 1.0, 2.0, 3.0, 4.0
。假设我们想要将从0到5的区间分为10个区间。我们可以按如下方式进行操作
sage: r_[0.0:5.0:11*j]
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])
《符号》 0.0:5.0:11*j
扩展到包括两个端点在内的0到5之间的11个等间距点的列表。请注意 j
是NumPy虚数,但它具有用于创建数组的特殊语法。我们可以将所有这些技术结合起来
sage: n = r_[0.0:5.0:11*j,int(5)*[0.0],-5.0:0.0]
sage: n
array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ,
0. , 0. , 0. , 0. , 0. , -5. , -4. , -3. , -2. , -1. ])
Another useful command is numpy.meshgrid()
, it produces meshed grids. As an
example suppose you want to evaluate f(x,y)=x^2+y^2 on a
an equally spaced grid with Delta x = Delta y = .25 for
0le x,yle 1. You can do that as follows
sage: import numpy
sage: j = complex(0,1)
sage: def f(x,y):
....: return x**2+y**2
sage: from numpy import meshgrid
sage: x = numpy.r_[0.0:1.0:5*j]
sage: y = numpy.r_[0.0:1.0:5*j]
sage: xx,yy = meshgrid(x,y)
sage: xx
array([[0. , 0.25, 0.5 , 0.75, 1. ],
[0. , 0.25, 0.5 , 0.75, 1. ],
[0. , 0.25, 0.5 , 0.75, 1. ],
[0. , 0.25, 0.5 , 0.75, 1. ],
[0. , 0.25, 0.5 , 0.75, 1. ]])
sage: yy
array([[0. , 0. , 0. , 0. , 0. ],
[0.25, 0.25, 0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75, 0.75, 0.75],
[1. , 1. , 1. , 1. , 1. ]])
sage: f(xx,yy)
array([[0. , 0.0625, 0.25 , 0.5625, 1. ],
[0.0625, 0.125 , 0.3125, 0.625 , 1.0625],
[0.25 , 0.3125, 0.5 , 0.8125, 1.25 ],
[0.5625, 0.625 , 0.8125, 1.125 , 1.5625],
[1. , 1.0625, 1.25 , 1.5625, 2. ]])
你可以看到 numpy.meshgrid()
生成一对矩阵,此处表示为 xx 和 yy ,以便 (xx[i,j],yy[i,j]) 有坐标 (x[i],y[j]) 。这很有用,因为要评估 f 在网格上,我们只需要对中的每一对条目进行计算 xx , yy 。由于NumPy自动按组件对数组执行算术运算,因此使用很少的代码就可以非常容易地在网格上计算函数。
一个有用的模块是 numpy.linalg
模块。如果你想解一个方程 Ax=b 做
sage: import numpy
sage: from numpy import linalg
sage: A = numpy.random.randn(5,5)
sage: b = numpy.array(range(1,6))
sage: x = linalg.solve(A,b)
sage: numpy.dot(A,x)
array([1., 2., 3., 4., 5.])
这将创建一个随机的5x5矩阵 A
,并解决 Ax=b 哪里 b=[0.0,1.0,2.0,3.0,4.0]
。中还有许多其他的例程 numpy.linalg
模块,这些模块大多是自解释的。例如,有 qr
和 lu
进行QR和LU分解的例程。还有一个命令 eigs
用于计算矩阵的特征值。你总是可以做到的 <function name>?
以获取文档,这对这些例程非常有用。
希望这能让您了解NumPy是什么样子的。您应该探索这个包,因为它有相当多的功能。