數學運算和基本函數
Julia 提供了所有數值基本類型中基本算術和位元運算子的完整集合,並提供標準數學函數的全面集合的可攜式、有效率的實作。
算術運算子
以下算術運算子支援所有基本數值類型
表達式 | 名稱 | 說明 |
---|---|---|
+x | 單元正號 | 恆等運算 |
-x | 單元負號 | 將值對應到其加法逆元 |
x + y | 二元正號 | 執行加法 |
x - y | 二元負號 | 執行減法 |
x * y | 乘號 | 執行乘法 |
x / y | 除號 | 執行除法 |
x ÷ y | 整數除法 | x / y,取整 |
x \ y | 反除法 | 等於 y / x |
x ^ y | 冪次 | 將 x 提升到 y 次方 |
x % y | 餘數 | 等於 rem(x,y) |
直接置於識別碼或括號之前的數字字面值,例如 2x
或 2(x+y)
,視為乘法,但優先權高於其他二元運算。有關詳細資訊,請參閱 數字字面值係數。
Julia 的提升系統讓混合參數類型的算術運算自然而然地「正常運作」。有關提升系統的詳細資訊,請參閱 轉換與提升。
÷ 符號可以透過在 REPL 或 Julia IDE 中輸入 \div<tab>
方便地輸入。有關更多資訊,請參閱 Unicode 輸入手冊。
以下是一些使用算術運算子的簡單範例
julia> 1 + 2 + 3
6
julia> 1 - 2
-1
julia> 3*2/12
0.5
(依慣例,我們傾向於將運算子間距縮小,如果它們在其他鄰近運算子之前套用。例如,我們通常會寫成 -x + 2
來反映首先對 x
進行否定,然後將 2
加到該結果中。)
在乘法中使用時,false
會作為一個強零
julia> NaN * false
0.0
julia> false * Inf
0.0
這對於防止已知為零的數量中 NaN
值的傳播很有用。請參閱 Knuth (1992) 以了解動機。
布林運算子
表達式 | 名稱 |
---|---|
!x | 否定 |
x && y | 短路與 |
x || y | 短路或 |
否定會將 true
變更為 false
,反之亦然。短路運算說明於連結的頁面中。
請注意,Bool
是整數類型,且所有通常的提升規則和數字運算子也定義在其中。
位元運算子
下列 位元運算子 支援所有原始整數類型
表達式 | 名稱 |
---|---|
~x | 位元非 |
x & y | 位元與 |
x | y | 位元或 |
x ⊻ y | 位元異或(互斥或) |
x ⊼ y | 位元非與(非與) |
x ⊽ y | 位元非或(非或) |
x >>> y | 邏輯位移右移 |
x >> y | 算術位移右移 |
x << y | 邏輯/算術位移左移 |
以下是位元運算子的一些範例
julia> ~123
-124
julia> 123 & 234
106
julia> 123 | 234
251
julia> 123 ⊻ 234
145
julia> xor(123, 234)
145
julia> nand(123, 123)
-124
julia> 123 ⊼ 123
-124
julia> nor(123, 124)
-128
julia> 123 ⊽ 124
-128
julia> ~UInt32(123)
0xffffff84
julia> ~UInt8(123)
0x84
更新運算子
每個二進制算術和位元運算子也都有更新版本,會將運算結果指派回其左運算元。二進制運算子的更新版本是將 =
放在運算子之後。例如,寫成 x += 3
等同於寫成 x = x + 3
julia> x = 1
1
julia> x += 3
4
julia> x
4
所有二進制算術和位元運算子的更新版本為
+= -= *= /= \= ÷= %= ^= &= |= ⊻= >>>= >>= <<=
更新運算子會重新繫結左手邊的變數。因此,變數的類型可能會改變。
julia> x = 0x01; typeof(x)
UInt8
julia> x *= 2 # Same as x = x * 2
2
julia> typeof(x)
Int64
向量化「點」運算子
對於每個二進制運算,例如 ^
,都有對應的「點」運算 .^
,會自動定義為對陣列執行逐元素 ^
。例如,[1,2,3] ^ 3
沒有定義,因為對(非正方形)陣列「立方」沒有標準的數學意義,但 [1,2,3] .^ 3
定義為計算逐元素(或「向量化」)結果 [1^3, 2^3, 3^3]
。對於一元運算,例如 !
或 √
,也有對應的 .√
,會逐元素套用運算子。
julia> [1,2,3] .^ 3
3-element Vector{Int64}:
1
8
27
更具體地說,a .^ b
會被解析為 「點」呼叫 (^).(a,b)
,它會執行 廣播 操作:它可以組合陣列和純量、相同大小的陣列(逐元素執行操作),甚至不同形狀的陣列(例如,組合行向量和列向量以產生矩陣)。此外,與所有向量化「點呼叫」一樣,這些「點運算子」都是融合的。例如,如果你計算陣列 A
的 2 .* A.^2 .+ sin.(A)
(或等效地使用 @.
巨集計算 @. 2A^2 + sin(A)
),它會對 A
執行單一迴圈,為 A
的每個元素 a
計算 2a^2 + sin(a)
。特別是,像 f.(g.(x))
這樣的巢狀點呼叫會被融合,而像 x .+ 3 .* x.^2
這樣的「相鄰」二元運算子等同於巢狀點呼叫 (+).(x, (*).(3, (^).(x, 2)))
。
此外,像 a .+= b
(或 @. a += b
)這樣的「點」更新運算子會被解析為 a .= a .+ b
,其中 .=
是融合的原地賦值運算(請參閱 點語法文件)。
請注意,點語法也適用於使用者定義的運算子。例如,如果你定義 ⊗(A,B) = kron(A,B)
以提供克羅內克積(kron
)的方便中綴語法 A ⊗ B
,則 [A,B] .⊗ [C,D]
將計算 [A⊗C, B⊗D]
,而無需額外的編碼。
將點運算子與數字文字結合可能會產生歧義。例如,不清楚 1.+x
是表示 1. + x
還是 1 .+ x
。因此,此語法不被允許,並且在這種情況下必須在運算子周圍使用空格。
數值比較
所有原始數值類型都定義了標準比較運算
運算子 | 名稱 |
---|---|
== | 相等 |
!= , ≠ | 不相等 |
< | 小於 |
<= , ≤ | 小於或等於 |
> | 大於 |
>= , ≥ | 大於或等於 |
以下是一些簡單範例
julia> 1 == 1
true
julia> 1 == 2
false
julia> 1 != 2
true
julia> 1 == 1.0
true
julia> 1 < 2
true
julia> 1.0 > 3
false
julia> 1 >= 1.0
true
julia> -1 <= 1
true
julia> -1 <= -1
true
julia> -1 <= -2
false
julia> 3 < -0.5
false
整數的比較方式為標準方式,也就是比較位元。浮點數的比較方式則依據 IEEE 754 標準
- 有限數值以一般方式排序。
- 正零等於負零,但不大於負零。
Inf
等於自身,且大於所有其他值,除了NaN
。-Inf
等於自身,且小於所有其他值,除了NaN
。NaN
不等於、不小於、也不大於任何值,包括自身。
最後一點可能令人驚訝,因此值得注意
julia> NaN == NaN
false
julia> NaN != NaN
true
julia> NaN < NaN
false
julia> NaN > NaN
false
且在使用 陣列 時可能會造成頭痛
julia> [1 NaN] == [1 NaN]
false
Julia 提供其他函式來測試數值的特殊值,這在雜湊金鑰比較等情況下會很有用
函式 | 測試是否 |
---|---|
isequal(x, y) | x 和 y 相同 |
isfinite(x) | x 是有限數值 |
isinf(x) | x 是無限大 |
isnan(x) | x 不是數字 |
isequal
視 NaN
為彼此相等
julia> isequal(NaN, NaN)
true
julia> isequal([1 NaN], [1 NaN])
true
julia> isequal(NaN, NaN32)
true
isequal
也可用於區分有號零
julia> -0.0 == 0.0
true
julia> isequal(-0.0, 0.0)
false
有號整數、無號整數和浮點數之間的混合型比較可能會很棘手。Julia 已非常小心地確保正確執行這些比較。
對於其他類型,isequal
預設會呼叫 ==
,因此如果您想要為自己的類型定義相等性,則只需新增一個 ==
方法。如果您定義自己的相等性函數,則您可能應該定義一個對應的 hash
方法,以確保 isequal(x,y)
暗示 hash(x) == hash(y)
。
鏈結比較
與大多數語言不同,在 Python 的顯著例外 中,比較可以任意鏈結
julia> 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5
true
在數值程式碼中,鏈結比較通常非常方便。鏈結比較使用 &&
算子進行純量比較,並使用 &
算子進行逐元素比較,這允許它們在陣列上執行。例如,0 .< A .< 1
會產生一個布林陣列,其中 A
的對應元素在 0 和 1 之間的項目為 true。
請注意鏈結比較的評估行為
julia> v(x) = (println(x); x)
v (generic function with 1 method)
julia> v(1) < v(2) <= v(3)
2
1
3
true
julia> v(1) > v(2) <= v(3)
2
1
false
中間表達式只會評估一次,而不是像表達式寫成 v(1) < v(2) && v(2) <= v(3)
時評估兩次。但是,鏈結比較中評估的順序是未定義的。強烈建議不要在鏈結比較中使用具有副作用(例如列印)的表達式。如果需要副作用,則應明確使用短路 &&
算子(請參閱 短路評估)。
基本函數
Julia 提供全面的數學函數和運算子集合。這些數學運算定義在廣泛的數值範圍內,包括整數、浮點數、有理數和複數,只要這些定義有意義。
此外,這些函數(就像任何 Julia 函數一樣)可以使用 點語法 f.(A)
以「向量化」方式應用於陣列和其他集合,例如 sin.(A)
將計算陣列 A
中每個元素的正弦值。
運算子優先順序和結合性
Julia 應用以下運算順序和結合性,從優先順序最高到最低
類別 | 運算子 | 結合性 |
---|---|---|
語法 | . 後接 :: | 左 |
指數 | ^ | 右 |
單元 | + - √ | 右[1] |
位元移位 | << >> >>> | 左 |
分數 | // | 左 |
乘法 | * / % & \ ÷ | 左[2] |
加法 | + - | ⊻ | 左[2] |
語法 | : .. | 左 |
語法 | |> | 左 |
語法 | <| | 右 |
比較 | > < >= <= == === != !== <: | 非結合 |
控制流程 | && 後接 || 後接 ? | 右 |
配對 | => | 右 |
指定 | = += -= *= /= //= \= ^= ÷= %= |= &= ⊻= <<= >>= >>>= | 右 |
如需取得 每個 Julia 運算子優先順序的完整清單,請參閱此檔案的頂端:src/julia-parser.scm
。請注意,其中一些運算子並未定義在 Base
模組中,但可能會由標準函式庫、套件或使用者程式碼提供定義。
您也可以透過內建函數 Base.operator_precedence
找出任何給定運算子的數值優先順序,其中數字越大,優先順序越高
julia> Base.operator_precedence(:+), Base.operator_precedence(:*), Base.operator_precedence(:.)
(11, 12, 17)
julia> Base.operator_precedence(:sin), Base.operator_precedence(:+=), Base.operator_precedence(:(=)) # (Note the necessary parens on `:(=)`)
(0, 1, 1)
也可以透過呼叫內建函式 Base.operator_associativity
來找到表示運算子結合性的符號
julia> Base.operator_associativity(:-), Base.operator_associativity(:+), Base.operator_associativity(:^)
(:left, :none, :right)
julia> Base.operator_associativity(:⊗), Base.operator_associativity(:sin), Base.operator_associativity(:→)
(:left, :none, :right)
請注意,例如 :sin
等符號會傳回優先權 0
。此值表示無效運算子,而非優先權最低的運算子。類似地,此類運算子會指定結合性 :none
。
數值文字係數,例如 2x
,會視為乘法,優先權高於任何其他二元運算,但 ^
例外,其中只有作為指數時,優先權才會比較高。
julia> x = 3; 2x^2
18
julia> x = 3; 2^2x
64
並置會解析為一元運算子,它在指數周圍具有相同的自然不對稱性:-x^y
和 2x^y
會解析為 -(x^y)
和 2(x^y)
,而 x^-y
和 x^2y
會解析為 x^(-y)
和 x^(2y)
。
數值轉換
Julia 支援三種形式的數值轉換,它們在處理不精確轉換時的方式不同。
符號
T(x)
或convert(T,x)
會將x
轉換為類型T
的值。- 如果
T
是浮點類型,結果會是最接近的可表示值,可能是正或負無限大。 - 如果
T
是整數類型,如果x
無法由T
表示,就會引發InexactError
。
- 如果
x % T
會將整數x
轉換為整數類型T
的值,與x
同餘模2^n
,其中n
是T
中的位元數。換句話說,二進位表示法會被截斷以符合。取捨函數 將類型
T
作為可選參數。例如,round(Int,x)
是Int(round(x))
的簡寫。
以下範例顯示不同的形式。
julia> Int8(127)
127
julia> Int8(128)
ERROR: InexactError: trunc(Int8, 128)
Stacktrace:
[...]
julia> Int8(127.0)
127
julia> Int8(3.14)
ERROR: InexactError: Int8(3.14)
Stacktrace:
[...]
julia> Int8(128.0)
ERROR: InexactError: Int8(128.0)
Stacktrace:
[...]
julia> 127 % Int8
127
julia> 128 % Int8
-128
julia> round(Int8,127.4)
127
julia> round(Int8,127.6)
ERROR: InexactError: trunc(Int8, 128.0)
Stacktrace:
[...]
請參閱 轉換與提升,了解如何定義自己的轉換與提升。
取捨函數
函式 | 說明 | 傳回類型 |
---|---|---|
round(x) | 將 x 取捨為最接近的整數 | typeof(x) |
round(T, x) | 將 x 取捨為最接近的整數 | T |
floor(x) | 將 x 取捨為小於或等於 -Inf | typeof(x) |
floor(T, x) | 將 x 取捨為小於或等於 -Inf | T |
ceil(x) | 將 x 取捨為大於或等於 +Inf | typeof(x) |
ceil(T, x) | 將 x 取捨為大於或等於 +Inf | T |
trunc(x) | 將 x 取捨為 0 | typeof(x) |
trunc(T, x) | 將 x 取捨為 0 | T |
除法函數
函式 | 說明 |
---|---|
div(x,y) ,x÷y | 截斷除法;商數取捨為 0 |
fld(x,y) | 向下取整除法;商數取捨為 -Inf |
cld(x,y) | 向上取整除法;商數取捨為 +Inf |
rem(x,y) ,x%y | 餘數;滿足 x == div(x,y)*y + rem(x,y) ;符號與 x 相同 |
mod(x,y) | 模數;滿足 x == fld(x,y)*y + mod(x,y) ;符號與 y 相同 |
mod1(x,y) | 偏移量為 1 的 mod ;傳回 r∈(0,y] (對於 y>0 )或 r∈[y,0) (對於 y<0 ),其中 mod(r, y) == mod(x, y) |
mod2pi(x) | 相對於 2pi 的模數;0 <= mod2pi(x) < 2pi |
divrem(x,y) | 傳回 (div(x,y),rem(x,y)) |
fldmod(x,y) | 傳回 (fld(x,y),mod(x,y)) |
gcd(x,y...) | x 、y ... 的最大公因數 |
lcm(x,y...) | x 、y ... 的最小公倍數 |
符號和絕對值函數
函式 | 說明 |
---|---|
abs(x) | 一個正值,其大小為 x |
abs2(x) | x 的平方大小 |
sign(x) | 表示 x 的符號,傳回 -1、0 或 +1 |
signbit(x) | 表示符號位元是否開啟(true)或關閉(false) |
copysign(x,y) | 一個值,其大小為 x ,符號為 y |
flipsign(x,y) | 一個值,其大小為 x ,符號為 x*y |
次方、對數和根號
函式 | 說明 |
---|---|
sqrt(x) ,√x | x 的平方根 |
cbrt(x) ,∛x | x 的立方根 |
hypot(x,y) | 直角三角形的斜邊,其他兩邊長度為 x 和 y |
exp(x) | 在 x 處的自然指數函數 |
expm1(x) | 當 x 接近零時,精確的 exp(x)-1 |
ldexp(x,n) | 對於 n 的整數值,有效率地計算 x*2^n |
log(x) | x 的自然對數 |
log(b,x) | x 的底數 b 對數 |
log2(x) | x 的底數 2 對數 |
log10(x) | x 的底數 10 對數 |
log1p(x) | 當 x 接近零時,精確的 log(1+x) |
exponent(x) | x 的二進位指數 |
有效數字 (x) | 浮點數 x 的二進位有效數字 (又稱尾數) |
對於為什麼 hypot
、expm1
和 log1p
等函數是必要且有用的概述,請參閱 John D. Cook 在這個主題上寫的兩篇優秀的部落格文章:expm1、log1p、erfc 和 hypot。
三角函數和雙曲函數
所有標準三角函數和雙曲函數也都有定義
sin cos tan cot sec csc
sinh cosh tanh coth sech csch
asin acos atan acot asec acsc
asinh acosh atanh acoth asech acsch
sinc cosc
這些都是單一參數函數,其中 atan
也接受兩個參數,對應傳統的 atan2
函數。
此外,sinpi(x)
和 cospi(x)
提供更精確的 sin(pi*x)
和 cos(pi*x)
計算。
為了使用度數而不是弧度來計算三角函數,請在函數後加上後綴 d
。例如,sind(x)
計算 x
的正弦,其中 x
以度數指定。具有度數變體的三角函數完整清單如下
sind cosd tand cotd secd cscd
asind acosd atand acotd asecd acscd
特殊函數
套件 SpecialFunctions.jl 提供許多其他特殊數學函數。