Julia Language
比較
サーチ…
構文
- x <y#
x
が厳密にy
より小さい場合 - x> y#
x
が厳密にy
より大きい場合 - x == y#もし
x
がy
と等しいならば - 代替的に、X ===のY位
x ≡ y
場合、x
にegalあるy
- X≤Y位代わり
x <= y
、場合x
以下であるy
- X≥のY位代わりに
x >= y
、場合x
以上でありy
- x≠y#あるいは、
x != y
、x
がy
と等しくなければ - x≈y#
x
がy
ほぼ等しい場合
備考
比較看板を裏返すことに注意してください。 Juliaは、対応するフリップバージョンを定義せずに、デフォルトで多くの比較関数を定義しています。例えば、
julia> Set(1:3) ⊆ Set(0:5)
true
しかし、それは動作しません
julia> Set(0:5) ⊇ Set(1:3)
ERROR: UndefVarError: ⊇ not defined
連鎖比較
一緒に使用される複数の比較演算子は、 &&
演算子を介して接続されているかのように連鎖されます。これは、以下のような読みやすく数学的に簡潔な比較チェーンに役立ちます。
# same as 0 < i && i <= length(A)
isinbounds(A, i) = 0 < i ≤ length(A)
# same as Set() != x && issubset(x, y)
isnonemptysubset(x, y) = Set() ≠ x ⊆ y
しかし、 a > b > c
とa > b && b > c
& a > b > c
間には重要な違いがa > b > c
ます。後者では、項b
が2回評価されます。これは普通の古いシンボルではあまり重要ではありませんが、用語自体に副作用がある場合は問題になります。例えば、
julia> f(x) = (println(x); 2)
f (generic function with 1 method)
julia> 3 > f("test") > 1
test
true
julia> 3 > f("test") && f("test") > 1
test
test
true
連鎖比較をより深く見て、それらがどのように解析され、 式に引き込まれているかを見て、それらがどのように機能するかを見てみましょう。まず、シンプルな比較を考えてみましょう。わかりましたが、単純な古い関数呼び出しです。
julia> dump(:(a > b))
Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol >
2: Symbol a
3: Symbol b
typ: Any
比較を連鎖させると、解析が変更されていることがわかります。
julia> dump(:(a > b >= c))
Expr
head: Symbol comparison
args: Array{Any}((5,))
1: Symbol a
2: Symbol >
3: Symbol b
4: Symbol >=
5: Symbol c
typ: Any
解析後、式は最終形式に下げられます。
julia> expand(:(a > b >= c))
:(begin
unless a > b goto 3
return b >= c
3:
return false
end)
実際にはa > b && b >= c
:と同じであることに注意してください。
julia> expand(:(a > b && b >= c))
:(begin
unless a > b goto 3
return b >= c
3:
return false
end)
序数
カスタム型、 序数を実装してカスタム比較を実装する方法を見ていきます。実装を簡素化するために、これらの数字の小さなサブセットに焦点を当てます。すべての序数はε0までですが、ε0までは含まれません。私たちの実装はスピードではなくシンプルさに焦点を当てています。しかし、実装は遅くはありません。
序数は、 Cantor標準形式で保存します。序数算術は可換ではないので、最重要語を最初に格納するという共通の慣習に従います。
immutable OrdinalNumber <: Number
βs::Vector{OrdinalNumber}
cs::Vector{Int}
end
カンター正規形はユニークであるため、単純に再帰的等価性によって等価性をテストすることができます。
バージョンv0.5では、これをコンパクトに行うための非常に優れた構文があります:
import Base: ==
α::OrdinalNumber == β::OrdinalNumber = α.βs == β.βs && α.cs == β.cs
それ以外の場合は、より一般的な関数を定義します。
import Base: ==
==(α::OrdinalNumber, β::OrdinalNumber) = α.βs == β.βs && α.cs == β.cs
注文を完了するには、このタイプに総注文があるので、 isless
関数をオーバーロードするisless
ます:
import Base: isless
function isless(α::OrdinalNumber, β::OrdinalNumber)
for i in 1:min(length(α.cs), length(β.cs))
if α.βs[i] < β.βs[i]
return true
elseif α.βs[i] == β.βs[i] && α.cs[i] < β.cs[i]
return true
end
end
return length(α.cs) < length(β.cs)
end
私たちの順序をテストするために、序数を作るためのいくつかのメソッドを作成することができます。もちろん、ゼロは、カンタールの正規形の項を持たないことで得られます。
const ORDINAL_ZERO = OrdinalNumber([], [])
Base.zero(::Type{OrdinalNumber}) = ORDINAL_ZERO
expω
を定義してω^α
を計算し、それを使って1とωを計算することができます:
expω(α) = OrdinalNumber([α], [1])
const ORDINAL_ONE = expω(ORDINAL_ZERO)
Base.one(::Type{OrdinalNumber}) = ORDINAL_ONE
const ω = expω(ORDINAL_ONE)
序数には完全に機能する順序付け関数があります。
julia> ORDINAL_ZERO < ORDINAL_ONE < ω < expω(ω)
true
julia> ORDINAL_ONE > ORDINAL_ZERO
true
julia> sort([ORDINAL_ONE, ω, expω(ω), ORDINAL_ZERO])
4-element Array{OrdinalNumber,1}:
OrdinalNumber(OrdinalNumber[],Int64[])
OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[],Int64[])],[1])
OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[],Int64[])],[1])],[1])
OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[OrdinalNumber(OrdinalNumber[],Int64[])],[1])],[1])],[1])
最後の例では、序数の印刷はより良いかもしれませんが、結果は期待通りです。
標準演算子
Juliaは非常に大きなセットの比較演算子をサポートしています。これらには
-
> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩴ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣
- ポイント1のすべてのシンボル
.
先頭にドット(.
)を付けると要素単位になります。 - 演算子
<:
、>:
、.!
、およびin
始まり、ドット(.
)で始めることはできません。
これらのすべてが標準のBase
ライブラリに定義されているわけではありません。ただし、他のパッケージでも適切に定義して使用することができます。
毎日の使用では、これらの比較演算子の大部分は関連性がありません。使用される最も一般的なものは、注文のための標準的な数学関数です。リストの構文セクションを参照してください。
Juliaの他のほとんどの演算子と同様に、比較演算子は関数であり、関数として呼び出すことができます。例えば、 (<)(1, 2)
は1 < 2
と同じ意味です。
==、===、isequalを使う
等号演算子には、 ==
、 ===
、 isequal
3つがあります。 (最後は実際に演算子ではありませんが、それは関数であり、すべての演算子は関数です)。
==
を使用する場合
==
は値の等しいものです。 2つのオブジェクトが現在の状態で同じ値を表すとき、 true
返します。
例えば、
julia> 1 == 1
true
しかしさらに
julia> 1 == 1.0
true
julia> 1 == 1.0 + 0.0im
true
julia> 1 == 1//1
true
上記の各等式の右辺は異なる型ですが、それでも同じ値を表します。
配列のような可変オブジェクトの場合、 ==
は現在の値を比較します。
julia> A = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> B = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> C = [1, 3, 2]
3-element Array{Int64,1}:
1
3
2
julia> A == B
true
julia> A == C
false
julia> A[2], A[3] = A[3], A[2] # swap 2nd and 3rd elements of A
(3,2)
julia> A
3-element Array{Int64,1}:
1
3
2
julia> A == B
false
julia> A == C
true
ほとんどの場合、 ==
は正しい選択です。
いつ使用するか===
===
は==
よりはるかに厳しい操作です。価値の平等の代わりに、それは公平性を測定する。 2つのオブジェクトは、プログラム自体によって互いに区別できない場合、egalです。したがって我々は
julia> 1 === 1
true
1
別のものから区別する方法がないため、 1
。しかし
julia> 1 === 1.0
false
なぜなら、 1
と1.0
は同じ値であるが、それらは異なる型であるため、プログラムはそれらを区別することができるからである。
さらに、
julia> A = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> B = [1, 2, 3]
3-element Array{Int64,1}:
1
2
3
julia> A === B
false
julia> A === A
true
最初は驚くように見えるかもしれません!どのようにプログラムが2つのベクトルA
とB
区別することができましたか?ベクトルは変更可能であるため、 A
変更でき、 B
とは異なる動作をします。しかし、それがA
どのように変更しても、 A
は常にA
自身と同じように動作します。だからA
はegalからA
、egalからB
へはではない。
この静脈に沿って続けて、観察する
julia> C = A
3-element Array{Int64,1}:
1
2
3
julia> A === C
true
A
をC
に代入A
と、 C
がA
エイリアスを付けたと言います。つまり、 A
別の名前になっています。 A
に対して行われた変更は、 C
によっても観察されます。したがって、 A
とC
違いを知る方法はないので、彼らはegalです。
isequal
使用する場合
==
とisequal
の違いは非常に微妙です。最大の違いは浮動小数点数の扱いです:
julia> NaN == NaN
false
おそらく驚くべき結果は、浮動小数点型(IEEE-754)のIEEE標準によって定義されています。しかし、これは並べ替えのようないくつかの場合には役に立ちません。これらの場合にはisequal
が提供されます。
julia> isequal(NaN, NaN)
true
スペクトルの裏側では、 ==
はIEEEの負のゼロと正のゼロを同じ値(IEEE-754で指定されているものと同じ)として扱います。しかし、これらの値はメモリ内に別個の表現を持っています。
julia> 0.0
0.0
julia> -0.0
-0.0
julia> 0.0 == -0.0
true
再び並べ替えの目的のために、 isequal
はそれらを区別します。
julia> isequal(0.0, -0.0)
false