# 初階 Matlab
>作者:蔡承佑
>
https://matlab.mathworks.com (IDE)
https://drive.matlab.com (folder)
## 介面操作
:::spoiler command history
儲存之前寫過的指令
:::
:::spoiler search
看指令如何使用
:::
## 快捷鍵
:::spoiler 停止執行
ctrl + c
:::
## 命名
一般變數 : Capital letter is lower case
Matrix : Capital letter is upper case
:::spoiler Function

:::
## Debug
設立紅色個flag,F10可以執行下一步
- Syntax Error (語法錯誤)
- Semantic Error (語義錯誤)
## 語法
### Precedence
:::spoiler

:::
### 版面
:::spoiler make stronger code

:::
:::spoiler Scripts
script (.m)
有點像是(.py)一次執行scripts內的全部指令
:::
:::spoiler help
help [command]
showing how to use that command
:::
:::spoiler 輸出 command 超過一行
加上...
:::
:::spoiler 儲存 Command Window
```python=
save
```
會產生.mat檔案
儲存包括變數
:::
:::spoiler 叫回 .mat
```python=
load
```
:::
:::spoiler 調整format
```python=
format compact
```
:::
:::spoiler log out
```python!
quit
```
:::
:::spoiler 清除上面的指令
```python=
clc
```
:::
:::spoiler delete variable
1. clear [variable name]
(without variable name would clear all variables)
2. click delete in workspace
:::
:::spoiler command
%
:::
:::spoiler ;,
; 執行但不會輸出
, 執行且輸出(不terminate)
:::
:::spoiler figure
產生新的圖表
:::
:::spoiler edit(產生檔案)
edit
:::
:::spoiler section(%%)
點選section -> 按 Run Section 就會執行 section 的 code
```matlab=
%% Examples of skipping remainder of iterations
%% Example 1
% Skipping is accomplished in the while condition.
ii = 1;
while ii < length(readings) && readings(ii) <= 100
readings(ii) = 0;
ii = ii + 1;
end
%% Example 2
% Skipping is acomplished with a break statement.
for ii = 1:length(readings)
if readings(ii) > 100
break;
else
readings(ii) = 0;
end
end
%% Example 3
% Shows that for-loop index retains is last value
% after the loop is exited. It's similar to Example 2,
% but omits the setting of values to 0 and prints the
% index of the first reading above 100.
for ii = 1:length(readings)
if readings(ii) > 100
break;
end
end
fprintf('First reading above 100 is at index %d.\n', ii);
```
==可以點擊publish==
:::
### variable
:::spoiler number
```python=
x = 9.65e12
y = 23e-2
```
:::
### function
可以寫在.m檔內
:::spoiler
```python=
function pretty_picture(N)
%command
t = 0:(.99*pi/2):N;
x = t.*sin(t);
y = t.*cos(t);
plot(x, y, 'k')
axis square
```
```python=
function [m,s] = stat(x)
n = length(x);
m = sum(x)/n;
s = sqrt(sum((x-m).^2/n));
end
```
:::
### image
:::spoiler show image
- method 1
>imshow('[image path]')
-method 2
>pretty_picture = imread('[image path]');
>image(pretty_picture)
:::
:::spoiler 關掉 x 軸 y 軸
axis off
:::
### math
:::spoiler 無窮大
inf
-inf
:::
:::spoiler 更號
sqrt(2)
:::
:::spoiler sin
- 依照弳(rad): sin(30)
- 依照度(deg): sind(30)
:::
:::spoiler plus
plus(number1, number2)
:::
:::spoiler 次方
^
:::
:::spoiler 虛數i
0.0000 + 1.0000i
:::
### 指令時間
:::spoiler tic toc
tic;
...
toc
:::
:::spoiler cputime
t0 = cputime; f(8); cputime - t0
:::
### open webpage
:::spoiler
```matlab=
function open_webpage
url = input('Enter the url: ','s');
if isempty(url)
fprintf("No url entered, so quitting.\n");
return;
end
search_time = datetime; % same as datetime("now")
status = web(url);
if status == 0 % started web browser
fprintf("At %s, you opened the web page at\n",search_time);
fprintf("%s\n",url);
else
fprint("Could not start web browser\n");
end
[~,weekday_name] = weekday(search_time,'long');
fprintf("Have a great %s!\n", weekday_name);
```
:::
## Matrix

*scalars also known as number
key word:
- end最後一行或最後一列
- : 所有row或column
:::spoiler Definition
- 2D array = "matrix"
- 1D array = "vector"
- Empty matrix: 1-by-0
:::
:::spoiler Matrix宣告
- 2D array
空白分割為column 分號分割為row
```python=
x = [1 4 7]
```
>x = 1 4 7
```python=
y = [1; 4; 7]
```
>y =
>1 <br/> 4 <br/> 7 <br/>
```python=
z = [1 4 7; 2 8 6]
```
>z =
>1 4 7
>2 8 6
- Empty matrix
x = []
- 初始化某一列某一行
==matlab 第一個是1不是0==
X(row_id, coloumn_id)
```python=
X = [1:4; 5:8; 9:12]
```
>X =
>1 2 3 4
>5 6 7 8
>9 10 11 12
```python=
X(2, 3)
```
>ans = 7
- Extend array
超過行列值的部分補0
```python=
X(4, 5)
```
>Index exceeds matrix dimensions
```python=
X(4, 5) = 456
```
>X =
>1 2 3 4 0
>5 6 7 8 0
>9 10 11 12 0
>0 0 0 0 456
- subarray
X(row_id, column_id)
```python=
X(2, [1 3])
```
>ans = 5 7
:::
:::spoiler : operator
array_name = begin : 遞增多少(沒有這個欄位就是1) : end(包括)
```python=
x = 1:3:10
```
>x = 1 4 7 10
```python=
x = 1:4
```
>x = 1 2 3 4
:::
:::spoiler colon function
```python=
colon(1, 7)
```
>ans = 1 2 3 4 5 6 7
:::
:::spoiler 查看 matrix 的維度長
```python=
X = [0 1 -1; 2.5 pi 100]
size(X)
```
>ans = 2 3
:::
### Combining Matrices
:::spoiler Definition

:::
:::spoiler 宣告

:::
### Transforming Matrices
:::spoiler Definition

:::
:::spoiler 宣告'
```python=
H = [1 2 3; 4 5 6]
G = H'
```
>H =
>1 2 3
>4 5 6
>G =
>1 4
>2 5
>3 6
```python=
(1:2:5)'
```
>ans =
>1
>3
>5
:::
### Arithmetics of Matrices
如果有常數 則是每個元素都跟這個常數進行四則運算
:::spoiler Add
- +
- sum(vector)
1. 將column的所有元素加起來
2. 若為 1Xn 則將vector所有元素相加
:::
:::spoiler Multiplication
1. Array Multiplication .*
>
2. Matrix Multiplication \*
>矩陣乘法
:::
:::spoiler Division
- Array Division (斜線下面篇哪裡 哪裡就是分子)
1. X./Y (over)
>
2. X.\Y (under)

:::
:::spoiler 次方
- Array (.^)
>
- Matrix (^)
>
:::
:::spoiler 餘數
rem(x, y), x 為被除數 y 為除數
:::
:::spoiler repmat

:::
### Matrix初始化技巧
:::spoiler Matrix 初始化技巧(善用zeros跟ones)
```matlab=
function M = sparse2matrix(cellvec)
sz = cellvec{1};
val = cellvec{2};
M = val*ones(sz);
for i = 3:length(cellvec)
el = cellvec{i};
M(el(1), el(2)) = el(3);
end
end
```
:::
## Function
:::spoiler Robustness
1. 用%加上註解在函式內容的最上面,當用help時會顯示
2. 用error function
3. 判斷可能的nargin跟nargout
4. 多用isscalar判斷是否為純量
```python=
function [table summa] = multable(n, m)
%MULTABLE multiplication table.
% T = MULTABLE(N) returns an N-by-N matrix
% containing the multiplication table for
% the integers 1 through N.
% MULTABLE(N,M) returns an N-by-M matrix.
% Both input arguments must be positive
% integers.
% [T SM] = MULTABLE(...) returns the matrix
% containing the multiplication table in T
% and the sum of all its elements in SM.
if nargin < 1
error('must have at least one input argument');
end
if nargin < 2
m = n;
end
table = (1:n)' * (1:m);
if nargout == 2
summa = sum(table(:));
end
```
:::
:::spoiler Polymorphism
輸入形式或數量不同但名稱相同的function
==利用 nargin 跟 nargout 達成==
```python=
function [table summa] = multable(n, m)
if nargin < 2
m = n;
end
table = (1:n)' * (1:m);
if nargout == 2
summa = sum(table(:));
end
```

==varargin 無限多輸入==
放在最後一個input
>
==varargout 無限多輸出==
>
:::
:::spoiler Definition

>function <回傳值> = <function_name>(<input>)
>...
>end
```python=
function a = myRand
a = 1 + rand(3, 4)*9;
end
```
```python=
function a = myRand(low, high)
a = low + rand(3, 4)*(high - low);
end
```
```python=
function [a, s] = myRand(low, high)
a = low + rand(3, 4)*(high - low);
v = a(:);
s = sum(v);
end
```
:::
:::spoiler Subfunction

:::
:::spoiler 全域變數
global <variable_name>
==宣告跟初始化要分開==
:::
:::spoiler Persistent variable
是一種local variable在呼叫第二次函式時不會改變,除非使用clear <function_name>
>
:::
:::spoiler return
可以中斷function藉由return
:::
:::spoiler Tool Box


==Matrix Building Function==
diag([7 3 9 1])
>ans =
>7 0 0 0
>0 3 0 0
>0 0 9 0
>0 0 0 1
rand(m, n)
>範圍是 0 到 1
randi(imax, m, n)
>用途: 生成均勻分布的隨機整數。
>imax: 指定生成的隨機整數的最大值,隨機整數將在 1 到 imax 之間(包括 imax)。
>m 和 n: 指定生成的隨機整數矩陣的尺寸。
randn(m, n)
>用途: 生成服從標準正態分布(均值為 0,標準差為 1)的隨機實數。
>m 和 n: 指定生成的隨機數矩陣的尺寸。
==判斷function==
isscalar()
isempty()
:::
:::spoiler Nested Function
function 內還有一個 function
inner function 的 variable, outer function不會有 (local scope)
outer function 的 variable, inner function會有 (non-local scope)
:::
### Function Handles
==可以用在cell但不行用在array==
:::spoiler variables

:::
:::spoiler plot

:::
:::spoiler 自訂義

也可以多個變數
xfn = @(x, y) x+y
:::
:::spoiler Return Multiple (deal)

:::
## Random
==random 的生成跟 rng的值有關==
所以每次重新打開輸入rand的值會是一樣的
想要更改可以改動rng => rng('shuffle')
:::spoiler

:::
## Input Output
:::spoiler input
<variable_name> = input('\<statement>');
```python=
function a = one_more
x = input('Gimme a number, buddy: ');
a = x + 1
```
:::
:::spoiler fprintf
用法像是 C 的 printf 包刮 %d %5.2f 特別的是可以為==矩陣==
```python=
fprintf('This concludes Lesson 3\n')
```
如果輸出的為特殊字符,例如: ' 、 % 、 \
則打兩次 '' 、 %% 、 \\
:::
:::spoiler sprintf
sprintf()將element 指定給變數
>
:::
## plot
:::spoiler 不要刷新表格(hold)
如果在一個表格輸入plot會蓋掉原本的圖,如果不想要蓋掉可以用hold
>hold on
>...
>hold off
:::
:::spoiler
help plot
doc plot
:::
:::spoiler 新增及切換下一個表格
figure(表格名稱)
:::
:::spoiler 關閉表格
close [表格名稱]
close all
:::
::: spoiler 表格新增方格線 (grid)
grid on
grid off
:::
:::spoiler 新增 x 軸 y 軸名稱 title
xlabel('[label name]')
ylabel('[label name]')
title('[tile of plot]')
:::
:::spoiler 改變 x 軸 y 軸範圍
axis([[x軸開頭], [x軸結束], [y軸開頭], [y軸結束]])
:::
:::spoiler length 顯示 vector 長度
```python=
x_coordinates = [1, 3, 10];
length(x_coordinates)
```
>ans = 3
:::
:::spoiler legend

:::
### type
:::spoiler 2D
1. plot([x vector], [y vector])
plot(x1, y1, x2, y2)
```python=
x_coordinates = [1, 3, 10]; %element vector
y_coordinates = [2, -4.2, 12.3];
plot(x_coordinates, y_coordinates); %plot function
```
>
2. plot([x vector], [y vector], [LineSpec])
plot(x1, y1, LineSpec1, x2, y2, LineSpec2)
```python=
plot(x_coordinates, y_coordinates, '*')
```
>
:::
:::spoiler bar
bar([x vector], [y vector])

:::
:::spoiler pie
```python=
pie([4 2 7 4 7])
```

:::
:::spoiler hist 分布圖
hist(<vector_name>)

:::
## Conditional Statement
:::spoiler Logical values
Non-zero: true
Zero: false
MATLAB returns 1 for true
:::
:::spoiler if
```matlab=
function guess_my_number(x)
if x == 42
fprintf('Congrats! You guessed my number!\n');
elseif x < 42
fprintf('Too small. Try again\n');
else
fprintf('Too big. Try again.\n')
end
```
:::
:::spoiler Relation Operator

可以用在matrix上
```python=
[4 -1 7 5 3] > [5 -9 6 5 -3]
```
>ans =
>0 1 1 0 1
```python=
[4 -1 7 5 3] <= 4
```
>ans =
>1 1 0 0 1
```python=
sum([14 9 3 14 8 3] == 14)
% 計算有幾個14
```
>ans = 2
:::
:::spoiler Combine Logical values

Array (& | )

:::
:::spoiler Nested if-statements(記得加end)
```matlab=
function ultimate_question_nested2(x)
if x <= 42
if x == 42
fprintf('Wow! You answered the question.\n');
else
fprintf('Too small. Try again.\n');
end
else
fprintf('Too big. Try again.\n');
end
```
:::
:::spoiler Switch Case
```matlab=
switch month
case {1, 3, 5, 7, 8, 10, 12}
day_in_month = 31;
case {4, 6, 9, 11}
day_in_month = 30;
case 2
if (mod(year, 4) == 0 && mod(year, 100) ~= 0) || mod(year, 400) == 0
day_in_month = 29;
else
day_in_month = 28;
end
otherwise
valid = false;
end
```
:::
## Loops


==1:5可以是任何array==
:::spoiler for
```matlab=
for n = 1:5
fprintf("%d\n", n)
end
```
```matlab=
function f = fibo(n)
if ( ~isscalar(n) || n < 1 || n ~= fix(n))
error('n must be a positive integer!');
end
f(1) = 1;
f(2) = 1;
for ii = 3:n
f(ii) = f(ii-2) + f(ii-1);
end
```
雙重迴圈 (matrix 遍歷)
```matlab=
[row col] = size(A);
for r = 1:row
fprintf('Working on row %d...\n',r);
for c = 1:col
P(r,c) = A(r,c) * A(r,c);
fprintf('(%d %d)\n',r,c);
end
end
```
:::
:::spoiler while
```matlab=
function [n total] = possum(limit)
total = 0;
n = 0;
while total <= limit
n = n + 1;
total = total + n;
end
fprintf('sum: %d count: %d\n', total, n);
```
:::
:::spoiler break
quit loop immediately
==只會break inner loop== 可善用flag
:::
## Logical Indexing (Special)
:::spoiler
>
index 的地方由 true/false 的 array 判斷
>
:::
:::spoiler logical
判斷array的元素是否為true
```matlab=
holmes = logical([1 -2 0 0 9.12 -2])
```
>holmes =
>1 1 0 0 1 1
:::
:::spoiler 二維陣列
如果是二維陣列呢?
>
因為陣列是column major
>
因為是column major改是由上往下 再由左往右
>
:::
## Preallocation
提前 allocate ,使的初始化時,不會重複宣告
:::spoiler
```matlab=
function prealloc
N = 5000;
A = zeros(N,N);
for ii = 1:N
for jj = 1:N
A(ii,jj) = ii*jj;
end
end
```
zeros(N, N) 就是在preallocate
:::
## Data Type
:::spoiler 查看變數type
1. class(<variable_name)
2. whos 查看目前所有type
:::
:::spoiler useful function (type check、range check、conversion)

out of range
>
:::
### Numbers
:::spoiler range of numbers

:::
### String
1. char array ('')
2. string ("")
:::spoiler string
視為double/char array
==char => %s==
如果要用 == 比較 : char matrix 的 dimension 必須相同
如果要創建string 的 matrix 長度必須相同,否則會遇到vercat(內建函式比較string)

:::
:::spoiler string function

==findstr(string, <want_to_find_what_string>)==
>
==strcmp(str1, str2), 1 is true, 0 is false==

==strcmpi(str1, str2), i means ignoring case==
>
==str2num(string)==
==num2str(number)==
>
==sprintf()將element 指定給變數==
>
==strrep(string, char1, char2)把string中的char1改成char2==
==circshift==
Caesear 加密法

extractBetween(s, 3, 8) 對付當s為string而非char array
extractBetween(s, str1, str2) 取str1 str2之間的string
:::
:::spoiler 注意char string
若要像 array 一樣對 string 操作,那他必須採用 char array 的方式表示('') 而不是 string ("")
>可以用 string() 、 char() 做切換
>
其他type轉string容易 => string()
但string轉其他type難 => 除了double() => ==先轉double再轉其他type==
>string(pi)
>ans = 3.14
>double("pi")
>ans = NaN
>double("17")
>ans = 17
>double('17')
>ans = 49 55
:::
### Struct
:::spoiler rule
1. homogeneity rule
>每個struct內的元素擁有相同field,但也僅限於第一層
>
>account(2)的owner內可能有不同元素
:::
:::spoiler

struct can be an array
>account(2).number = 1
>account(2).name = 'Charlie'
>account ==%查看所有的field==
:::
:::spoiler struct function

==isfield(struct, 'field')==
==struct = rmfield(struct, 'field')==
>
==struct = struct(...)==
>
:::
### Cells
pointer
()可以視為指標的值
{row, col}可以視為指標指向的值
:::spoiler
跟 char matrix 不同,每個元素不用等長了
```matlab=
%% The Ultimate Legend of Big John
page{1} = 'You could find him on the field almost any day.';
page{2} = 'Tall, dark hair, and eyes of steel gray.';
page{3} = 'They say he pulled a Frisbee ''bout half a mile,';
page{4} = 'And when he''d stick in the corner, you could almost catch a smile';
page{5} = 'On Big John.';
%% Print it
fprintf('\n');
for ii = 1:length(page)
fprintf('%s\n',page{ii});
end
fprintf('\n');
```
:::
:::spoiler Cell array



>c{1} is number c(1) is cell
>
:::
:::spoiler cell function

:::
### Datatime
:::spoiler setting
HOME -> Preferences -> Command Window
>
datetime(year, month, day)
datetime(year, month, day, hour, month, second)
timezones 看時區
>
format
>
:::
:::spoiler Duration
- hours(2.5)、years(3)、days(3)、months()、seconds()、duration(hours, minutes, seconds)
==calyears(整數)=>直接加一年,years()=>事實上是加365.2425天==
所以+calyears(1)還會是同一天,但+years(1)就不一定了
```matlab=
right_now = datetime("now")
three_years_from_now = right_now + years(3)
```
- .years year()
>
>
- arrithmetic
```matlab=
missing_days = days(datetime(1764, 5, 17) - datetime(1764, 2, 15))
```
:::
### Function Handles
==可以用在cell但不行用在array==
:::spoiler variables

:::
:::spoiler plot

:::
## File I/O (like wsl)
:::spoiler pwd
show current path (linux format)
Windows format => ['C:', strrep(pwd, '/', '\')]
:::
:::spoiler ls

:::
:::spoiler cd
get into directory
:::
:::spoiler mkdir
mkdir(file_name)
:::
:::spoiler rmdir
rmdir(file_name)
:::
:::spoiler save
儲存目前變數於.mat
:::
:::spoiler load
load .mat檔
可以決定load哪些
loat .mat檔的名稱 變數名 變數名
:::
:::spoiler 讀取excel檔案
==[num, text, raw] = xlsread("path")==
class(num) = double
class(text) = string
class(raw) = cell
他們都可以用 pointer 或 array 的方式處理
[num, string] = xlsread("path")
[~, ~, everything] = xlsread("path")

tmep 可以用 ~ 代替指讀取string

:::
:::spoiler Text file
- Opening: fid = fopen(filename, permission)
- 如果沒有成功開啟fid<0
- Closing: fclose(fid)
- File identifier (fid): a handle to refer to the file once open
- Permission: what we want to do with the file
- read, write, overwrite, append
>
- 輸入file
- fid = fopen(filename, 'w+t');
- fprintf(fid, '%s\n', Title_1);
```matlab=
function write_temp_precip_txt(filename)
Title_1 = 'Climate Data for Nashville, TN';
Title_2 = '(Average highs (F), lows (F), and precip (in)';
Label_1 = ' High ';
Label_2 = ' Low ';
Label_3 = 'Precip';
Mo_1 = {'Jan','Feb','March','April','May','June'};
Mo_2 = {'July','Aug','Sep','Oct','Nov','Dec'};
Data_1 = [
46 28 3.98
51 31 3.7
61 39 4.88
70 47 3.94
78 57 5.08
85 65 4.09];
Data_2 = [
89 69 3.78
88 68 3.27
82 61 3.58
71 49 2.87
59 40 4.45
49 31 4.53];
fid = fopen(filename,'w+t');
if fid < 0
fprintf('error opening file\n');
return;
end
fprintf(fid,'%s\n',Title_1);
fprintf(fid,'%s\n',Title_2);
fprintf(fid,'\n');
fprintf(fid,' %s%s%s\n',Label_1,Label_2,Label_3);
for ii = 1:6
fprintf(fid,'%5s: ',Mo_1{ii});
fprintf(fid,'%5.2f,%5.2f,%5.2f\n',Data_1(ii,:));
end
fprintf(fid,'\n');
fprintf(fid,' %s%s%s\n',Label_1,Label_2,Label_3);
for ii = 1:6
fprintf(fid,'%5s: ',Mo_2{ii});
fprintf(fid,'%5.2f,%5.2f,%5.2f\n',Data_2(ii,:));
end
fclose(fid);
```
- read file
- one line at a time
```matlab=
function view_text_file(filename)
fid = fopen(filename, 'rt');
if fid < 0
error('error opening file %s\n\n', filename);
end
% Read file as a set of strings, one string per line:
oneline = fgets(fid);
while ischar(oneline)
fprintf('%s', oneline) % display one line
oneline = fgets(fid);
end
fprintf('\n');
fclose(fid);
```
:::
- Reading lines into string variables is easy
- Parsing these strings to get numerical data is much harder
- Not covered
- Binary files (.dat) are more suited for numerical data
:::spoiler Writing binary files

:::
:::spoiler Reading binary files

:::
:::spoiler binary files (dimension one)


:::