GNU Octave是一种以高级编程语言为特色的软件,主要用于数值计算和绘图。通过Octave可以非常方便的进行矩阵运算、求解联立方程组、计算矩阵特征值和特征向量等。本篇文档主要内容是Octave基础命令、数据格式、绘制图形、Octave脚本编写、Octave函数编程等内容。另外,此文档会不断补充常见使用场景。
当我们使用C++来处理矩阵运算方面的问题确实显得过于复杂时,C++这样的编程语言不原生的支持一些数学概念或者生成图表。Octave 是专为解决这类问题而设计的,所以很多时候用Octave来编写软件的原型或者数学部分,因为这样能够很快的检验其算法的正确性。
另外GNU Octave自由、免费、而且轻量级。MATLAB的Licence很难获取,故我选择GNU Octave。
如果是初次使用Octave,英文比较好的话可以直接阅读官方文档 https://octave.org/octave.pdf,文档里有最详细的介绍,如果只是想了解日常的使用方式那么看这篇文章足矣,如果遇到到其他在本文中没有出现过的场景,我会翻译后补充在本文中。
安装Octave可以参考 https://www.gnu.org/software/octave/download ,Mac下直接使用brew安装即可,如果需要GUI界面,可以参考如下方式:
bashbrew reinstall octave--with-qt
我们通常在命令行界面运行Octave,每个命令依次输入命令行中,并以回车结束。Octave是一门解释型语言,即每个命令通过解释器转化为机器语言。
命令行所处的ENV,也就是本次打开Octave的上下文ENV。所以对于Octave有工作空间的概念,一切的函数文件、脚本文件都只对当前的工作空间生效。
通过who
命令可以查看本次所处于的工作空间的变量,clear用于清除已经存在的变量,也可以指定变量清除:
octaveoctave:1> who octave:2> a = 10; b = 20; c = a + b; octave:3> who Variables visible from the current scope: a b c octave:4> d = 200; octave:5> who Variables visible from the current scope: a b c d octave:6> clear octave:7> who octave:8> d = 200; octave:9> clear d octave:10> who octave:11> clear octave:12> a = 10; b = 20; c = a + b; octave:13> who Variables visible from the current scope: a b c octave:14> clear b octave:15> who Variables visible from the current scope: a c octave:16>
如果你不了解某个 Octave 命令的功能或者是你需要找一个特定的函数,Octave 本身强大的帮助系统会很有用。最基本的使用帮助系统的方式就是:help commandname,比如查看clear命令、查看sin函数:
octaveoctave:1> help clear 'clear' is a built-in function from the file libinterp/corefcn/variables.cc -- clear -- clear PATTERN ... -- clear OPTIONS PATTERN ... Delete the names matching the given PATTERNs thereby freeing memory... octave:2> help sin 'sin' is a built-in function from the file libinterp/corefcn/mappers.cc -- sin (X) Compute the sine for each element of X in radians. See also: asin, sind, sinh...
退出Octave的交互式环境的时候,你将丢失你所创建的变量。如果你需要在工作的中途退出 Octave,那么你可以保存当前会话的数据并在之后进行重新载入:
octaveoctave:1> a = [1:10]; octave:2> b = [1:0.5:10]; octave:3> save anyname octave:4> exit zchanglin@mbp OctaveWK % ls anyname octave-workspace zchanglin@mbp OctaveWK % cat anyname # Created by Octave 6.4.0, Thu Jan 27 17:45:40 2022 CST <zchanglin@mbp.local> # name: a # type: matrix # rows: 1 # columns: 10 1 2 3 4 5 6 7 8 9 10 # name: b # type: matrix # rows: 1 # columns: 19 1 1.5 2 2.5 3 3.5 4 4.5 5 5.5 6 6.5 7 7.5 8 8.5 9 9.5 10
这将整个工作空间上的变量存储到当前目录下一个名为 anyname 的文件中,这样你可以退出 Octave,之后重新启动 Octave 程序,通过输入:load anyname
octaveoctave:1> load anyname octave:2> a a = 1 2 3 4 5 6 7 8 9 10 octave:3> b b = Columns 1 through 14: 1.0000 1.5000 2.0000 2.5000 3.0000 3.5000 4.0000 4.5000 5.0000 5.5000 6.0000 6.5000 7.0000 7.5000 Columns 15 through 19: 8.0000 8.5000 9.0000 9.5000 10.0000 octave:4>
将重新载入之前保存的命名空间,并从你中断的地方重新开始工作。
同样的如果只是想保存某些变量而非全部保存,只需要在上述命令中加入变量名称即可:
octaveoctave:1> a = 10; b = 20; c=30; octave:2> save anyname a b; octave:3> exit zchanglin@mbp OctaveWK % octave GNU Octave, version 6.4.0 ..... octave:1> load anyname; octave:2> a a = 10 octave:3> b b = 20 octave:4> c error: 'c' undefined near line 1, column 1 octave:5>
在上述例子中,可能你注意到了结尾加不加分号的区别,加了分号表示不显示本条指令的结果,加了的话就会展示本条指令的结果,这与MATLAB是一致的。
Octave 在 UNIX 环境下通过在终端中输入octave来启动,在启动octave 之后,程序一般会显现如下信息:
octavezchanglin@mbp ~ % octave GNU Octave, version 6.4.0 Copyright (C) 2021 The Octave Project Developers. This is free software; see the source code for copying conditions. There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, type 'warranty'. Octave was configured for "x86_64-apple-darwin19.6.0". Additional information about Octave is available at https://www.octave.org. Please contribute if you find this software useful. For more information, visit https://www.octave.org/get-involved.html Read https://www.octave.org/bugs.html to learn how to submit bug reports. For information about changes from previous versions, type 'news'. octave:1> (2+8)/5 * 2 - 3 ans = 1 octave:2> a = (2+8)/5 * 2 - 3; octave:3> a a = 1
各种计算符号的优先级与常规的一致,比如括号有最大优先级,其次为乘方,其次为乘除运算,最后为加减运算。
Octave 提供了一系列的常用数学函数,其中的常用部分函数如下所示。像 C++ 中调用函数一样,Octave 通过输入函数名和括号中的输入参数来调用函数,其中自然对数e、圆周率pi 都是Octave已经定义的常量(ans代表上一次的计算结果,就像一个普通的科学计算器一样),例如:
octaveoctave:1> sin(90 * pi/180) ans = 1 octave:2> sin(30 * pi/180) ans = 0.5000 octave:3> cos(60 * pi/180) ans = 0.5000 octave:4> pi ans = 3.1416 octave:5> e ans = 2.7183 octave:6> log(e) ans = 1 octave:7> 2 * ans ans = 2 octave:8> abs(5) + abs(-5) ans = 10 octave:9>
内建函数 | 描述 | 内建函数 | 描述 |
---|---|---|---|
cos | 余弦函数(弧度制) | abs | 绝对值函数 (复数取模 ) |
sin | 正弦函数(弧度制) | sign | 符号函数 |
tan | 正切函数(弧度制) | round | 四舍五入 |
cot | 余切函数(弧度制) | floor | 近似为比它小的最大整数 |
log | 以 e 为底的指数函数 | ceil | 近似为比它大的最小整数 |
log10 | 以 10 为底的指数函数 | fix | 向 0 方向近似 |
exp | 指数函数 | rem | 求余数 |
sinh | 双曲正弦函数 | cosh | 双曲余弦函数 |
tanh | 双曲正切函数 | coth | 双曲余切函数 |
asin | 反正弦函数 | acos | 反余弦函数 |
acosh | 反双曲余弦函数 | asinh | 反双曲正弦函数 |
构造矩阵或者向量的方法有很多。其中最直接简单的方法就是在一个方括号 [] 中给出其元素,也可以通过已经定义的向量来定义新的向量,中间使用空格隔开或者逗号隔开:
octaveoctave:1> a=[6 5 4] a = 6 5 4 octave:2> b=[3 7]; octave:3> c = [a 1 3 4 b] c = 6 5 4 1 3 4 3 7 octave:4> d = [a,1,3,4] d = 6 5 4 1 3 4 octave:5>
有时候我们需要快速的定义向量,可以使用冒号表达式来定义:
octaveoctave:1> a = [5:10] # 定义元素为5-10的向量,默认步长为1 a = 5 6 7 8 9 10 octave:2> b = [1:0.5:3] # 中间的0.5表示步长 b = 1.0000 1.5000 2.0000 2.5000 3.0000 octave:3>
常规方式定义矩阵:
octaveoctave:1> a = [10, 20, 30; 1, 2, 3] # 定义矩阵a a = 10 20 30 1 2 3 octave:2> b = 5:7 # 定义向量b b = 5 6 7 octave:3> a = [10, 20, 30; 1, 2, 3; b] # 向量参与矩阵构建 a = 10 20 30 1 2 3 5 6 7 octave:4>
通过函数定义矩阵与向量
函数 | 描述 |
---|---|
zeros(M, N) | 创建一个 M×N 的零矩阵 |
ones(M, N) | 创建一个 M×N 的全1矩阵 |
rand(M, N) | 创建一个 M×N 的随机矩阵 |
linspace(x1, x2, N) | 创建一个 N 个元素的向量, 均匀分布于 x1 和 x2 |
logspace(x1, x2, N) | 创建一个 N 个元素的向量,指数分布与 10x1 和 10x2 之间 |
octaveoctave:3> zeros(3, 3) ans = 0 0 0 0 0 0 0 0 0 octave:4> ones(2, 2) ans = 1 1 1 1 octave:5> linspace(10, 20, 3) ans = 10 15 20 octave:6> logspace(10, 20, 3) ans = 1.0000e+10 1.0000e+15 1.0000e+20 octave:7>
Octave 无法用单屏显示一个元素超多的向量或者矩阵,有一种READ MORE的模式,通过 more off
命令关闭,
通过 more on
命令开启;比如现在查看一个1000个元素的向量:
octaveoctave:1> v = 1:1000 v = Columns 1 through 21: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Columns 22 through 42: 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 Columns 43 through 63: ...... -- less -- (f)orward, (b)ack, (q)uit # 按q退出 octave:2> more off
向量中的元素通过括号()
进行访问,而第一个元素的编号为 1, 而不是像其他编程语言那样从0开始。例如:
octaveoctave:1> a = [1:10] octave:2> a(5) ans = 5 octave:3> a(5) + a(8) ans = 13 octave:4> b = a(4:6) # 冒号的表示法同样可以用于声明向量中的元素的范围 b = 4 5 6 octave:5> length(b) # 求向量b的长度 ans = 3
使用Octave来对向量或者矩阵进行计算非常方便,不用像C/C++那样写多重for循环,先来看看向量数乘,对向量中所有元素都除以一个数的操作与乘法类似:
octaveoctave:1> a = 2:6 a = 2 3 4 5 6 octave:2> 2*a ans = 4 6 8 10 12 octave:3> 2*a ans = 4 6 8 10 12 octave:4> a - 1 ans = 1 2 3 4 5 octave:5> a + 2 ans = 4 5 6 7 8
两个向量的相乘遵循矩阵的乘法法则,向量乘法并不是对应元素的相乘。如果要进行对应元素的乘除法, 你可以使用 .
运算符,每个算符前的 .
表示为一个元素对元素的计算,比如:
octaveoctave:1> a = 1:5 a = 1 2 3 4 5 octave:2> b = 6:10 b = 6 7 8 9 10 octave:3> a.*b # 向量元素相乘 ans = 6 14 24 36 50 octave:4> a.^2 # 向量元素二次方 ans = 1 4 9 16 25 octave:7> a = rand(3,4) # 创建3*4随机矩阵 a = 0.592680 0.824473 0.504916 0.893063 0.976128 0.249468 0.866887 0.148853 0.933072 0.228585 0.069300 0.384276 octave:8> b = rand(4,3) # 创建3*4随机矩阵 b = 0.6803 0.1361 0.1822 0.5374 0.6651 0.6490 0.3831 0.5916 0.1651 0.2554 0.3941 0.9914 octave:9> a * b # 矩阵乘法 ans = 1.2678 1.2797 1.6118 1.1682 0.8703 0.6305 0.8823 0.4715 0.7108 octave:10> a.*b # 矩阵元素相乘 error: product: nonconformant arguments (op1 is 3x4, op2 is 4x3) octave:11> c = rand(3,4) # 创建3*4随机矩阵 c = 0.042975 0.462963 0.221173 0.524956 0.694888 0.486257 0.416091 0.127658 0.042671 0.760997 0.251399 0.655109 octave:12> a * c # 矩阵乘法 error: operator *: nonconformant arguments (op1 is 3x4, op2 is 3x4) octave:13> a .* c # 矩阵元素相乘 ans = 0.025471 0.381701 0.111674 0.468819 0.678300 0.121305 0.360704 0.019002 0.039815 0.173952 0.017422 0.251743
以创建一个以60度为间隔的角度值,并作为 sin 函数的输入作为例子,进行绘图:
octaveoctave:1> x=[0:pi/3:2*pi]; # 定义X轴数据集 octave:2> y = sin(x); octave:3> plot(x,y); # 绘制函数 octave:5> xlabel('Angle'); # X轴标注 octave:6> ylabel('Value'); # Y轴标注 octave:7> title('Graph of y=sin(x)'); # 图表标题 octave:8> grid on; # 开启网格 octave:10> hold; # 图像保持(避免被下一个函数图形覆盖) octave:11> y2 = sin(x) + 0.5; # 定义另一个函数 octave:12> plot(x,y2); # 绘制函数 octave:13> legend('Sine','Sine+0.5'); # 绘制图例 octave:14> hold; octave:15> print('./graph1.png','-dpng'); # 打印当前图表到工作区
plot函数其实有更多的选项,主要是设置线型和颜色。例如,使用红色和圆圈来画出之前的图片,输入:
octaveplot(x, y,'ro');
Octave提供了print 命令来将图片打印到默认的打印机上。
另外如果需要绘制多幅图表,则使用 figure
命令新建窗口即可。
下表中列出了plot 命令中的颜色和样式选项,可以通过 help plot 命令查看:
w 白色 | m 品红 | c 青色 | r 红色 |
---|---|---|---|
g 绿色 | b 蓝色 | y 黄色 | k 黑色 |
. 点 | o 圆圈 | x x 形 | + + 号 |
* 星号 | s 正方形 | d 菱形 | v 下三角 |
< 左三角 | > 右三角 | p 五角星 | p 五角星 |
- 实线 | : 虚线 | -. 点划线 | – 虚线 |
对于一些重复输入的命令,完全可以将这一系列的命令存入一个 Octave 脚本之中。这种包含 Octave 命令的文本文件是 Octave 程序的基本形式,当在 Octave 中执行这样的脚本的时候,其效果与将这些命令一行行输入效果是一样的。而且 Octave 脚本是普通的文本文件,方便修改,脚本需要有 .m
作为后缀。需要执行脚本的时候向 Octave 终端输入脚本文件的名称即可,但是无需加上 .m
后缀。
还需要注意的点就是如果执行一个脚本,最好将脚本加入到当前的工作空间中,如果不想手动添加到工作空间,则需要使用 addpath 命令添加脚本所在的工作目录,然后使用 savepath 命令保存即可。
现在定义一个用于计算和绘制整流正弦波的脚本 abssin.m :
octave%Script to calculate and plot a rectified sine wave t=linspace(0,10,100); y=abs(sin(t)); % get abs plot(t,y); title('Rectified Sine Wave'); xlabel('t');
命令行执行此脚本如下,为了让使用者容易得到帮助信息,在每个脚本的头几行写上有关该脚本的注释是一个很好的习惯:
octave>> abssin >> help abssin % 查看脚本的帮助文档,其实就是自己定义的注释内容 'abssin' is a script from the file ...\OctaveWK\abssin.m Script to calculate and plot a rectified sine wave Additional help for built-in functions and operators is available in the online version of the manual. Use the command 'doc <topic>' to search the manual index. Help and information about Octave is also available on the WWW at https://www.octave.org and via the help@octave.org mailing list.
假设你使用了很多的脚本之后你会对这些脚本混淆不清。要想知道你拥有哪些脚本,你可以输入 what 命令来获取一个你当前所有的脚本和数据的列表:
octave>> what M-files in directory xxx\Desktop\OctaveWK: abssin.m
使用 Octave 能非常方便地执行向量和矩阵的计算,但是如果要实现更加复杂的功能,还需要引入一些标准的程序语言特性。比如 if...else、if...elseif、switch、for、while 等控制语句。
符号 | 意义 | 例子 |
---|---|---|
== | 等于 | if x == y |
~= | 不等于(区别于常规) | if x ~= y |
> | 大于 | if x > y |
>= | 大于等于 | if x >= y |
< | 小于 | if x < y |
<= | 小于等于 | if x <= y |
& | 与 | if x== 1 & y>2 |
| | 或 | if x==1 | y>2 |
~ | 非 | x ~= y |
在命令行界面中执行 if 语句时,Octave 会等到你输入 end 语句之后才执行整个表达式。 |
octave>> a = 10; b = 20; >> if a > b c = 3 else c = 4 end c = 4
控制语句中又很多的逻辑表达式——表达式根据相应条件具有真或者假的属性。在 Octave 中,逻辑表达式返回值根据真或者假分别返回 1 或者 0,这与C语言一样,0表示假,非0表示真。
下面是 switch 控制的用法,是不是很简单?
octave>> switch a case 0 disp('a is zero'); case 1 disp('a is one'); otherwise disp('a is not a binary digit'); end a is one >>
很多场景下都是向量或者矩阵运算,但是仍会存在少数情况需要 for 或者 while 来搞定:
octave>> for n=1:5 nf(n)=factorial(n); end >> disp(nf) 1 2 6 24 120 >> n = 5; >> while n > 0 n=n-1 end n = 4 n = 3 n = 2 n = 1 n = 0 >>
一下篇文章将介绍 Octave 的函数定义,多返回值的函数,矩阵与向量的常见计算方法以及更多的绘图技巧。
本文作者:Tim
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!