Поиск…


Синтаксис

  • x <y #, если x строго меньше y
  • x> y #, если x строго больше y
  • x == y #, если x равно y
  • x === y # альтернативно x ≡ y , если x равно 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 ; в последнем, термин 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

Так как нормальная форма Кантора единственна, мы можем проверить равенство просто через рекурсивное равенство:

0.5.0

В версии v0.5 есть очень хороший синтаксис для этого компактно:

import Base: ==
α::OrdinalNumber == β::OrdinalNumber = α.βs == β.βs && α.cs == β.cs
0.5.0

В противном случае определите функцию как более типичную:

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ω для вычисления ω^α и использовать его для вычисления 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. Все следующие последовательности юникода: > < >= ≥ <= ≤ == === ≡ != ≠ !== ≢ ∈ ∉ ∋ ∌ ⊆ ⊈ ⊂ ⊄ ⊊ ∝ ∊ ∍ ∥ ∦ ∷ ∺ ∻ ∽ ∾ ≁ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≣ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊃ ⊅ ⊇ ⊉ ⊋ ⊏ ⊐ ⊑ ⊒ ⊜ ⊩ ⊬ ⊮ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⋍ ⋐ ⋑ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋲ ⋳ ⋴ ⋵ ⋶ ⋷ ⋸ ⋹ ⋺ ⋻ ⋼ ⋽ ⋾ ⋿ ⟈ ⟉ ⟒ ⦷ ⧀ ⧁ ⧡ ⧣ ⧤ ⧥ ⩦ ⩧ ⩪ ⩫ ⩬ ⩭ ⩮ ⩯ ⩰ ⩱ ⩲ ⩳ ⩴ ⩵ ⩶ ⩷ ⩸ ⩹ ⩺ ⩻ ⩼ ⩽ ⩾ ⩿ ⪀ ⪁ ⪂ ⪃ ⪄ ⪅ ⪆ ⪇ ⪈ ⪉ ⪊ ⪋ ⪌ ⪍ ⪎ ⪏ ⪐ ⪑ ⪒ ⪓ ⪔ ⪕ ⪖ ⪗ ⪘ ⪙ ⪚ ⪛ ⪜ ⪝ ⪞ ⪟ ⪠ ⪡ ⪢ ⪣ ⪤ ⪥ ⪦ ⪧ ⪨ ⪩ ⪪ ⪫ ⪬ ⪭ ⪮ ⪯ ⪰ ⪱ ⪲ ⪳ ⪴ ⪵ ⪶ ⪷ ⪸ ⪹ ⪺ ⪻ ⪼ ⪽ ⪾ ⪿ ⫀ ⫁ ⫂ ⫃ ⫄ ⫅ ⫆ ⫇ ⫈ ⫉ ⫊ ⫋ ⫌ ⫍ ⫎ ⫏ ⫐ ⫑ ⫒ ⫓ ⫔ ⫕ ⫖ ⫗ ⫘ ⫙ ⫷ ⫸ ⫹ ⫺ ⊢ ⊣ ;
  2. Все символы в пункте 1, которым предшествует точка ( . ), Которая должна быть сделана поэлементно;
  3. Операторы <: , >: , .! , и in , которому не может предшествовать точка ( . ).

Не все из них имеют определение в стандартной Base библиотеке. Тем не менее, они доступны для других пакетов для определения и использования по мере необходимости.

В повседневном использовании большинство из этих операторов сравнения не имеют отношения к делу. Наиболее распространенными являются стандартные математические функции для упорядочения; см. раздел «Синтаксис» для списка.

Как и большинство других операторов в Julia, операторы сравнения являются функциями и могут быть вызваны как функции. Например, (<)(1, 2) идентично по значению 1 < 2 .

Использование ==, === и isequal

Существует три оператора равенства: == , === и 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 является эгальным для A , но не имеет значения для 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 , поэтому они являются эгальными.

Когда использовать isequal

Разница между == и isequal очень тонкая. Самая большая разница в том, как обрабатываются числа с плавающей запятой:

julia> NaN == NaN
false

Этот неожиданный результат определяется стандартом IEEE для типов с плавающей точкой (IEEE-754). Но это не полезно в некоторых случаях, например, для сортировки. 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


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow