Julia Language
तुलना
खोज…
वाक्य - विन्यास
- x <y # यदि
x
कड़ाई सेy
से कम है - x> y # अगर
x
कड़ाई सेy
से अधिक है - x == y # यदि
x
y
बराबर है - x === y # वैकल्पिक रूप से
x ≡ y
,x ≡ y
, यदिx
y
सेy
- एक्स ≤ y # वैकल्पिक रूप से
x <= y
, अगरx
के बराबर की तुलना में कम या ज्यादा हैy
- एक्स ≥ y # वैकल्पिक रूप से
x >= y
, अगरx
के बराबर की तुलना में या अधिक से अधिक हैy
- x if y # वैकल्पिक रूप से
x != y
, यदिx
y
बराबर नहीं है - x। y # यदि
x
लगभगy
बराबर है
टिप्पणियों
चारों ओर तुलना संकेतों को लहराने के बारे में सावधान रहें। जूलिया इसी फ़्लिप्ड संस्करण को परिभाषित किए बिना डिफ़ॉल्ट रूप से कई तुलना कार्यों को परिभाषित करता है। मसलन, कोई चला सकता है
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
महत्वपूर्ण अंतर है; उत्तरार्द्ध में, b
शब्द का मूल्यांकन दो बार किया जाता है। यह सादे पुराने प्रतीकों के लिए बहुत ज्यादा मायने नहीं रखता है, लेकिन अगर बात खुद साइड इफेक्ट की हो तो बात हो सकती है। उदाहरण के लिए,
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)
क्रमसूचक संख्या
हम देखेंगे कि एक कस्टम प्रकार, क्रमिक संख्याओं को लागू करके कस्टम तुलनाओं को कैसे लागू किया जाए। कार्यान्वयन को सरल बनाने के लिए, हम इन संख्याओं के एक छोटे उपसमुच्चय पर ध्यान केंद्रित करेंगे: सभी क्रमिक संख्याएँ, लेकिन ε₀ शामिल नहीं हैं। हमारा कार्यान्वयन सादगी पर केंद्रित है, गति पर नहीं; हालाँकि, कार्यान्वयन धीमा नहीं है।
हम सामान्य संख्या को उनके कैंटर द्वारा सामान्य रूप में संग्रहीत करते हैं। चूंकि ऑर्डिनल अंकगणितीय सराहनीय नहीं है, इसलिए हम सबसे महत्वपूर्ण शर्तों को संग्रहीत करने का सामान्य सम्मेलन लेंगे।
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
फ़ंक्शन को ओवरलोड करना चाहिए:
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ω
को 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])
अंतिम उदाहरण में, हम देखते हैं कि क्रमिक संख्याओं का मुद्रण बेहतर हो सकता है, लेकिन परिणाम उम्मीद के मुताबिक है।
मानक संचालक
जूलिया तुलना ऑपरेटरों के एक बहुत बड़े सेट का समर्थन करता है। इसमें शामिल है
- निम्नलिखित सभी यूनिकोड अनुक्रम:
> < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩴ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣
- बिंदु 1 में सभी प्रतीक, एक बिंदु (
.
) द्वारा पूर्ववर्ती किए जा रहे हैं; - ऑपरेटरों
<:
,>:
,.!
, औरin
है, जो एक डॉट से पहले नहीं किया जा सकता (.
)।
इन सभी की मानक Base
लाइब्रेरी में परिभाषा नहीं है। हालांकि, वे उचित रूप में परिभाषित करने और उपयोग करने के लिए अन्य पैकेजों के लिए उपलब्ध हैं।
रोजमर्रा के उपयोग में, इन तुलना ऑपरेटरों में से अधिकांश प्रासंगिक नहीं हैं। उपयोग किए जाने वाले सबसे आम आदेश देने के लिए मानक गणितीय कार्य हैं; सूची के लिए सिंटैक्स अनुभाग देखें।
जूलिया में अधिकांश अन्य ऑपरेटरों की तरह, तुलना ऑपरेटर कार्य हैं और इन्हें कार्यों के रूप में कहा जा सकता है। उदाहरण के लिए, (<)(1, 2)
1 < 2
अर्थ में समान है।
==, ===, और असमान का उपयोग करना
तीन समानता ऑपरेटर हैं: ==
, ===
, और isequal
। (अंतिम वास्तव में एक ऑपरेटर नहीं है, लेकिन यह एक फ़ंक्शन है और सभी ऑपरेटर कार्य हैं।)
कब उपयोग करें ==
==
मूल्य समानता है। यह 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
ज्यादातर समय, ==
सही विकल्प है।
कब उपयोग करना है ===
===
==
तुलना में कहीं अधिक कठोर ऑपरेशन है। मूल्य समानता के बजाय, यह समानता को मापता है। यदि वे कार्यक्रम के द्वारा एक दूसरे से अलग नहीं हो सकते हैं तो दो वस्तुएं समान हैं। इस प्रकार हमारे पास है
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
जो पहली बार में आश्चर्यजनक लग सकता है! कार्यक्रम दो वैक्टर 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
को असाइन करके, हम कहते हैं कि C
ने A
को अलियास किया है। यही है, यह A
लिए सिर्फ एक और नाम बन गया है। A
द्वारा किए गए किसी भी संशोधन को C
द्वारा भी देखा जाएगा। इसलिए, A
और C
बीच अंतर बताने का कोई तरीका नहीं C
, इसलिए वे ईगल हैं।
कब उपयोग करना है 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