Octave 中的數值資料包含純量(scalar)、向量(vector)與矩陣(matrix),其中的值可為實數或複數。
純量(Scalars)
最簡單的數值資料就是常數純量,其表示方法可以是整數、浮點數、分數或是科學記號, 例如:
105
1.05e+2
1050e-1
以上三個數值是一樣的。若要表示複數:
3 + 4i
3.0 + 4.0i
0.3e1 + 40e-1i
這三個複數也都表示同樣的數值,其中 i 代表複數的虛部,也就是 -1 的平方根。在 Octave 中要使用 i 來表示複數的虛部時,數字與 i 之間不能有空白,例如:
3 + 4 i
數字與 i 之間若有空白 Octave 就會產生錯誤。
代表複數虛部的
i亦可以用j、I或J來替代,這四個字母的功能相同。
Octave 在儲存常數純量時預設是使用雙精度浮點數(double precision)來儲存,若是複數則使用兩個雙精度浮點數儲存。
double (x)
double(x) 會將 x 轉換為雙精度浮點數後傳回,可用於純量或是矩陣。
complex (x)
complex (re, im)
complex(x) 會傳回實部為 x 虛部為 0 的複數。complex(re, im) 會傳回實部為 re 虛部為 im 的複數。使用 complex() 函數通常會比直接寫 a + bi 的形式方便,例如:
complex ([1, 2], [3, 4])
矩陣(Matrices)
定義矩陣
在 Octave 要定義一個矩陣很簡單,矩陣的大小 Octave 會自動依照使用者所輸入的資料來決定,每個列以分號(;)分隔,而一個列中的每個元素則是以逗號(,)分隔,例如:
a = [1, 2; 3, 4]
這樣會產生一個 2 乘 2 的矩陣 a。
在指定矩陣可以使用各種的表示方式,只要其組合起來的維度是正確的都可以被 Octave 接受,例如:
b = [a, a]
這會將兩個 a 合併起來變成一個 2 乘 4 的矩陣。而若是組合起來的維度不正確,就會出現錯誤:
[a, 1]
Octave 會顯示其維度不符合:
error: number of rows must match (1 != 2) near line 5, column 5
所有在中括弧中的資料 Octave 都會視為矩陣,Octave 會自動判斷是否要將空白與換行轉換為元素與列的分隔符號,所以上面的矩陣 a 也可以寫成這樣:
a = [1 2
3 4]
但有時候這種寫法會產生混淆,例如:
[1 - 1]
會被視為 1 減 1,所以會得到 0,而
[1 -1]
則會被視為 [1, -1]。
在中括弧中呼叫函數時,也會發生類似的問題:
[sin (pi)]
會被視為 [sin, (pi)] 而產生錯誤,因為 sin() 函數必須要有一個傳入的參數,要避免產生錯誤必須把中間多餘的空白去除或是再加入一個小括弧:
[(sin (pi))]
用於矩陣轉置的單引號(')周圍的空白也要注意,例如:
a = [1, 2; 3, 4]
[a a']
若是單引號前多一個空白:
[a a ']
就會造成錯誤:
error: unterminated string constant
parse error:
syntax error
>>> [a a ']
^為了避免上述的問題,在表示矩陣時最好不要省略分號與逗號。
矩陣輸出格式
當使用者輸入的變數是矩陣時,Octave 會將矩陣的內容排版後輸出在螢幕上,以下的函數可以控制矩陣的輸出格式:
val = output_max_field_width ()
old_val = output_max_field_width (new_val)
查詢或設定數值在輸出時的最大字元寬度。
val = output_precision ()
old_val = output_precision (new_val)
查詢或設定數值在輸出時的最小有效位數。
output_max_field_width() 與 output_precision() 函數配合可以設定各種輸出格式,使用者可以使用 format() 函數設定其組合,請參考輸入與輸出。
val = split_long_rows ()
old_val = split_long_rows (new_val)
若是矩陣太大無法一次顯示在螢幕上,Octave 預設會將矩陣的列(row)切開,每次顯示矩陣中一部分的列,split_long_rows() 函數可以查詢或設定矩陣在輸出時是否要將列(row)切開輸出,例如:
rand(2, 10)
輸出為
ans = Columns 1 through 7: 0.085634 0.136640 0.455903 0.681633 0.687501 0.533536 0.461752 0.708830 0.679109 0.119020 0.975902 0.110367 0.488791 0.518949 Columns 8 through 10: 0.196560 0.808889 0.576050 0.670522 0.913750 0.866018
Octave 在輸出矩陣中非常大或非常小的數值時,會自動切換成科學記號來表示,這樣可以確保矩陣中每個元素都可以顯示較多的有效數字,若是想以固定的位數來表示矩陣中的數值,可以透過下面的函數更改設定,但更改此設定有可造成輸出的數值被誤判,因此不建議更改。
val = fixed_point_format ()
old_val = fixed_point_format (new_val)
查詢或設定是否將矩陣數值以固定位數輸出,若是設定以固定位數輸出,Octave 會以 scaled format 輸出矩陣:
fixed_point_format(1)
x=[100, 0.2; 0.3, 0.9]
輸出為
x = 1.0e+02 * 1.00000 0.00200 0.00300 0.00900
輸出的第一個數值 1.0e+02 是一個係數,下方矩陣中每個數值乘上這係數就會得到原來的值,有時候這樣的輸出會產生過大的誤差:
fixed_point_format(0)
logspace(1, 7, 5)'
fixed_point_format(1)
logspace(1, 7, 5)'
因此在 fixed_point_format() 不是設定為 0 時,要注意輸出是否會產生錯誤。
空矩陣
在數學上矩陣的兩個維度有可能其中一個是 0 或是兩個都是 0 ,Octave 亦允許使用者使用一個維度或兩個維度都是 0 的矩陣,而空矩陣在輸出時預設會使用 [] 符號表示,這個可以使用下列函數設定:
val = print_empty_dimensions ()
old_val = print_empty_dimensions (new_val)
查詢或設定是否要將空矩陣的維度與 [] 符號一起輸出,例如:
zeros(3, 0)
會輸出
ans = [](3x0)
空矩陣也可以用來刪除矩陣的行或列,請參考運算。
範圍(Ranges)
範圍(Ranges)的表示法可以很方便的表示一個元素間距離相等的列向量(row vector),其表示方法是以冒號(:)分隔開始值、間距與結束值,例如要產生 1 到 3 的列向量,元素間的間距為 0.5,則:
1 : 0.5 : 3
產生的列向量等同於 [1, 1.5, 2, 2.5, 3]。間距亦可以是負的,這像會產生遞減的列向量:
3 : -0.5 : 1
若是將間距省略,則 Octave 會使用預設的間距 1 來產生列向量:
1 : 3
產生的列向量等同於 [1, 2, 3]。
使用範圍表示法所得到的列向量有可能不包含範圍的結束值,例如:
1.2 : 0.3 : 2.6
若是要確保端點的值可以被納入,請使用 linspace() 函數。
除了在必要的情況,Octave 不會自動將範圍轉換成列向量,而會以範圍的形式儲存,因為列向量通常需要較多的記憶體來儲存,例如 1:10000 在 32 位元的系統就需要佔用 80,000 個位元組。當 Octave 中含有一些運算時,Octave 也會避免將範圍表示法轉換為列向量,例如:
a = 2*(1:1e7) - 1;
b = 1:2:2e7-1;
a 與 b 所產生的列向量是一樣的,但 b 不需要建立一個長度是 10,000,000 的列向量。
範圍表示法無法接受間距為 0 的情況(也就是所有列向量的元素都相同),要產生這樣的列向量可以使用 ones() 函數,例如:
ones(1, 10)
若範圍表示法中包含運算式,Octave 在接受範圍表示法時會自動判斷此運算式是否為常數,若計算結果是常數,則會以此常數替代運算式。
單精度浮點數(Single Precision)
Octave 支援單精度浮點數運算,大部份的函數也都可以使用單精度浮點數的參數,並且以單精度浮點數傳回結果,單精度浮點數的建立可使用 single() 函數。
single (x)
single(x) 會將 x 轉換為單精度浮點數後傳回,可用於純量或是矩陣。例如:
sngl = single(rand(2, 2))
class(sngl)
有許多函數可以直接設定傳回值為單精度浮點數,例如:
ones (2, 2, "single")
zeros (2, 2, "single")
eye (2, 2, "single")
NaN (2, 2, "single")
NA (2, 2, "single")
Inf (2, 2, "single")
整數(Integer)
Octave 支援整數的純量或矩陣,包含 8、16、32 與 64 位元的有號(signed)與無號(unsigned)整數,由於許多的運算需要使用浮點數,整數在遇到浮點運算時會自動轉換成浮點數,因此整數通常只用於儲存數值而不用來計算。
最常見的整數矩陣是將一般的浮點數矩陣轉換為整數矩陣,例如:
fmat = rand (2, 2)
輸出為
fmat = 0.70290 0.92763 0.80579 0.31735
以 int32() 函數將 fmat 轉換為 32 位元的整數矩陣:
int32(fmat)
輸出為
ans = 1 1 1 0
由結果看出浮點數會被轉換為最接近的整數。
isinteger (x)
isinteger(x) 可判斷 x 是否為整數。
isinteger(8)會傳回false,因為 Octave 所有的常數預設都是使用雙精度浮點數儲存。
int8 (x)
int8(x) 會將 x 轉換為 8 位元的有號整數後傳回。
uint8 (x)
uint8(x) 會將 x 轉換為 8 位元的無號整數後傳回。
int16 (x)
int16(x) 會將 x 轉換為 16 位元的有號整數後傳回。
uint16 (x)
uint16(x) 會將 x 轉換為 16 位元的無號整數後傳回。
int32 (x)
int32(x) 會將 x 轉換為 32 位元的有號整數後傳回。
uint32 (x)
uint32(x) 會將 x 轉換為 32 位元的無號整數後傳回。
int64 (x)
int64(x) 會將 x 轉換為 64 位元的有號整數後傳回。
uint64 (x)
uint64(x) 會將 x 轉換為 64 位元的無號整數後傳回。
intmax (type)
intmax(type) 會傳回 type 類型整數能夠儲存的最大數值,type 可以指定的類型有:"int8"、 "uint8"、 "int16"、 "uint16"、 "int32"、"uint32"、"int64"、"uint64"。
intmin (type)
intmin(type) 會傳回 type 類型整數能夠儲存的最小數值,type 可以指定的類型有:"int8"、 "uint8"、 "int16"、 "uint16"、 "int32"、"uint32"、"int64"、"uint64"。
intwarning (action)
intwarning (s)
s = intwarning (...)
控制整數在轉換與運算時的警告訊息設定,可用的參數有:
"query":查詢目前的警告訊息的設定,若沒有指定輸出參數,則會直接將輸出顯示在螢幕上,若是有指定輸出參數則會傳回"identifier"與"state"的資料結構。"on":將警告訊息開啟,若是沒有指定輸出參數,則不會有傳回值,若有指定輸出參數則會傳回原本的設定。"off":將警告訊息關閉,若是沒有指定輸出參數,則不會有傳回值,若有指定輸出參數則會傳回原本的設定。
例如查詢目前的設定:
intwarning("query")
關閉警告訊息,並將目前的設定儲存為 old_s:
old_s = intwarning("off")
將設定還原:
intwarning(old_s)
整數運算(Integer Arithmetic)
Octave 支援一些基本的整數運算,例如:加(+)、減(-)、乘(.*)、除(./),這些運算可以用於相同類型的整數,也就是說兩個 32 位元的整數可以直接相加,但一個 16 位元與一個 32 位元的整數就無法直接相加。例如:
a = int16(10)
b = int32(10)
a + b
a 是一個 16 位元的整數而 b 是一個 32 位元的整數,若是直接相加就會出現錯誤:
error: binary operator `+' not implemented for `int16 scalar' by `int32 scalar' operations
在 Octave 中對於整數的算術運算會先將整數轉換為雙精度浮點數,經過運算之後在轉換回原來的整數類型,而雙精度浮點數只有 53 個位元可以用來表示整數,所以在 Octave 中無法進行 64 位元的整數運算。
在使用整數運算時,必須注意 underflow 與 overflow 的問題,這個問題會發生在使用的整數類型無法表示計算的結果,例如無號整數無法表示 10 - 20,而 Octave 會確保整數運算的結果是最接近真實值的整數,因此無號整數運算 10 - 20 的結果是 0。
Octave 在進行整數除法的運算時,會將結果轉為最接近實際值的整數(使用 round),這與一般的程式語言不同(使用 floor),例如:
int32(5) ./ int32(8)
結果是 1。
idivide (x, y, op)
使用不同的規則進行整數除法運算,Octave 預設的整數除法運算 a ./ b 會將結果轉為最接近實際值的整數(使用 round),而 idivide() 函數可以使用其他的規則來進行個別元素的整數除法運算,其中 op 參數可以指定要使用的整數除法規則:
"fix":將結果朝向0的方向轉為最接近的整數。"round":將結果轉為最接近實際值的整數。"floor":將結果朝向負無限大的方向轉為最接近的整數。"ceil":將結果朝向正無限大的方向轉為最接近的整數。
若不指定 op 參數,預設會使用 "fix"。例如:
idivide (int8 ([-3, 3]), int8 (4), "fix")
輸出為
ans = 0 0
idivide (int8 ([-3, 3]), int8 (4), "round")
輸出為
ans = -1 1
idivide (int8 ([-3, 3]), int8 (4), "ceil")
輸出為
ans = 0 1
idivide (int8 ([-3, 3]), int8 (4), "floor")
輸出為
ans = -1 0
位元操作(Bit Manipulations)
Octave 提供了許多操控位元的函數,最基本的就是取得與設定數值中的指定位元:
bitset (a, n)
bitset (a, n, v)
bitset() 會設定 a 中第 n 個位元值為 v,參數 n 為大於 0 的整數;參數 v 為 1 或 0,若是不指定則預設為 1。例如:
a = 10
dec2bin(a)
b = bitset(a, 1)
dec2bin(b)
X = bitget (a, n)
bitget(a, n) 傳回 a 中第 n 個位元值,例如:
bitget(4, 3)
參數 n 亦可以向量或範圍表示法指定:
bitget(4, 1:4)
bitget(4, 4:-1:1)
bitget(4, [1, 3])
在 Octave 中除了 bitcmp() 函數之外,所有的位元操作函數都可以接受純量或陣列,當一個以上的參數是陣列時,這些陣列必須要有相同的大小,而 Octave 會針對陣列中每個元素個別進行位元運算,若只有一個參數是陣列而其餘的參數是純量時,純量的參數會自動重複以配合陣列的元素進行運算,例如:
bitget(100, 8:-1:1)
第一個參數是純量,第二個參數是 1 乘 8 陣列,因此 Octave 會將第一個參數重複 8 次,就像這樣:
bitget(100 * ones(1, 8), 8:-1:1)
這兩個寫法是一樣的。
Octave 的位元運算都是針對整數的位元作運算,即便傳入的數值是浮點數,Octave 也會自動轉為整數,例如:傳入浮點數 10 會被視為整數,因此其各個位元的值為 [1, 0, 1, 0],而不是表示浮點數的位元值。
在位元運算中常常會需要查詢可以被浮點數表示的最大的整數,尤其是在建立遮罩(mask)的時候,這時可以使用 bitmax() 函數:
bitmax ()
傳回可以被浮點數表示的最大整數,在 IEEE-754 的系統中是 2^53-1。這個函數可以看成是 intmax() 函數的浮點數版本。
Octave 也支援 and、or、xor 位元運算:
bitand (x, y)
bitand(x, y) 傳回 x 與 y 的位元 AND 運算,x 與 y 為大於或等於0 且小於或等於 bitmax 的無號整數。
bitor (x, y)
bitor(x, y) 傳回 x 與 y 的位元 OR 運算,x 與 y 為大於或等於0 且小於或等於 bitmax 的無號整數。
bitxor (x, y)
bitxor(x, y) 傳回 x 與 y 的位元 XOR 運算,x 與 y 為大於或等於0 且小於或等於 bitmax 的無號整數。
bitcmp (a, k)
bitcmp(a, k) 傳回 a 的位元 NOT 運算結果,也就是 a 的補數(complement),參數 k 是指定傳回運算結果的位元數,若不指定則預設是 log(bitmax) + 1,例如:
bitcmp(7, 4)
dec2bin(11)
dec2bin(bitcmp(11, 6))
bitshift (a, k)
bitshift (a, k, n)
bitshift(a, k, n) 傳回 a 位元 shift 的結果。參數 k 是指定 shift 的距離,正整數代表向左,負整數代表向右;參數 n 是指定傳回運算結果的位元數,若不指定則預設是 log(bitmax) + 1,例如:
bitshift (eye (3), 1)
bitshift (10, [-2, -1, 0, 1, 2])
經過位元 shift 運算超出左右兩邊邊界的位元將會遺失。
Octave 的位元 shift 運算會將負整數的負號保留,例如:
bitshift (-10, -1)
bitshift (int8 (-1), -1)
bitshift (int8 (-1), -1) 的運算結果是 -1,原因是在於 int8 類型的 -1 ,其二進位表示為 [1, 1, 1, 1, 1, 1, 1, 1],經過位元 shift 運算之後,還是維持一樣的值。
邏輯值(Logical Values)
Octave 內建支援邏輯值(true 與 false)與相關的邏輯運算:AND(&)、OR(|)與 NOT(!)。
除了邏輯運算之外,Octave 亦允許在算術運算式中使用邏輯值,邏輯值在進行算術運算時會自動轉為雙精度浮點數,true 轉會 1,false 轉換為0,因此
true * 22 - false / 6
結果是 22。
邏輯值亦可以使用在矩陣的索引與巢狀陣列上,當矩陣使用一個邏輯像像當作索引時,會將矩陣中對應邏輯向量為 true 的元素取出,例如:
data = [1, 2; 3, 4]
idx = (data <= 2)
data(idx)
這會將 data 矩陣中小於或等於 2 的元素取出,另外一種比較精簡的寫法:
data(data <= 2)
邏輯值的建立可以從數值資料轉換而得到,或是直接使用 true 與 false 函數。
logical (arg)
logical(arg) 會將 arg 轉換為邏輯值(0 轉換為 false,除了0 以外的值轉換為 true)。例如:
logical([-1, 0, 1])
與
[-1, 0, 1] != 0
所得到的結果是相同的。
true (x)
true (n, m)
true (n, m, k, ...)
傳回各種維度的邏輯值陣列,陣列中所有的元素都是 true,例如 3 乘 3 的方陣:
true(3)
3 乘 2 的矩陣:
true(3, 2)
更高維度的陣列:
true(3, 4, 2)
false (x)
false (n, m)
false (n, m, k, ...)
傳回各種維度的邏輯值陣列,陣列中所有的元素都是 false,使用方法與 true() 函數相同。
數值類型轉換
在 Octave 中有許多運算子可以接受不同的變數類型,而 Octave 預設會將精確度較高的數值類型轉換為較低的數值類型再進行運算,這與一般程式語言中的習慣是不同的,例如:將一個 8 位元的整數與浮點數相加:
a = uint8(1) + 1
這裡的浮點數 1 會被轉型為 8 位元的整數,因此所得到的 a 是一個 8 位元的整數。而單精度浮點數與雙精度浮點數相加:
b = single(1) + 1
所得到的 b 則是單精度浮點數。
以下是各種類型的數值運算組合與所得到的結果類型:
| 混合運算 | 結果 |
|---|---|
| double OP single | single |
| double OP integer | integer |
| double OP char | double |
| double OP logical | double |
| single OP integer | integer |
| single OP char | single |
| single OP logical | single |
這個規則亦可套用至函數的參數,例如:
min(single(1), 0)
這會傳回單精度浮點數的數值。
陣列中的值以索引的方式指定成其他類型的數值時,陣列中的數值類型不會改變,例如:
x = ones(2, 2)
x(1, 1) = single(2)
得到的 x 還是維持 2 乘 2 的雙精度浮點數。
判斷數值類型
數值在運算時常常會因為遇到不同類型的數值而轉換,而在很多情況下不同的變數類型會產生不同的結果,例如內建的 abs() 函數,當輸入值是實數時,它會傳回數值的絕對值,而當輸入的值是複數時,它會傳回此複數的長度。以下是 abs() 函數的定義:
function a = abs (x)
if (isreal (x))
a = sign (x) .* x;
elseif (iscomplex (x))
a = sqrt (real(x).^2 + imag(x).^2);
endif
endfunction
Octave 有許多函數可以查詢數值目前的類型:
isnumeric (x)
判斷 x 是否為數值物件。
isreal (x)
判斷 x 是否為實數。
isfloat (x)
判斷 x 是否為浮點數。
iscomplex (x)
判斷 x 是否為複數。
ismatrix (x)
判斷 x 是否為矩陣。
isvector (x)
判斷 x 是否為向量。
isscalar (x)
判斷 x 是否為純量。
issquare (x)
判斷 x 是否為方陣(square matrix),若為方陣則傳回 x 的維度,否則傳回0。
issymmetric (x, tol)
判斷 x 是否為對稱矩陣(symmetric matrix),若為對稱矩陣則傳回 x 的維度,否則傳回0,tol 參數用來設定容許的誤差值,判定 x 是否為對稱矩陣是依據
norm (x - x.’, inf) / norm (x, inf) < tol
來判定的,若省略 tol 參數,則會使用系統的精確度。
isdefinite (x, tol)
判斷 x 是否為正定對稱矩陣(symmetric positive definite),若為正定對稱矩陣則傳回 1,否則傳回 -1,tol 參數用來設定容許的誤差值,若省略 tol 參數,則會使用 100 倍的系統精確度。
islogical (x)
判斷 x 是否為邏輯值。
isprime (x)
判斷 x 是否為質數。