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打印数组时没有显式显示数据类型,那么类型要么是硬件浮点型,要么是int型。
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,那么数组存储为machine 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数组都有一个shape属性。这是一个很有用的属性
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=numpy.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
展开为包含11个间距相等的0到5点的列表,包括两个端点。请注意 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. ])
另一个有用的命令是 numpy.meshgrid()
生成网格。作为一个例子,假设您想评估 f(x,y)=x^2+y^2 在等间距网格上 Delta x = Delta y = .25 对于 0le x,yle 1 . 你可以这样做
sage: import numpy
sage: j=numpy.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是什么样的感觉。您应该研究一下这个包,因为它有更多的功能。