Recherche…


Syntaxe

  • x <y # si x est strictement inférieur à y
  • x> y # si x est strictement supérieur à y
  • x == y # si x est égal à y
  • x === y # alternativement x ≡ y , si x est égal à y
  • x ≤ y # alternativement x <= y , si x est inférieur ou égal à y
  • x ≥ y # alternativement x >= y , si x est supérieur ou égal à y
  • x ≠ y # alternativement x != y , si x n'est pas égal à y
  • x ≈ y # si x est approximativement égal à y

Remarques

Faites attention à ne pas renverser les signes de comparaison. Julia définit de nombreuses fonctions de comparaison par défaut sans définir la version retournée correspondante. Par exemple, on peut courir

julia> Set(1:3) ⊆ Set(0:5)
true

mais ça ne marche pas

julia> Set(0:5) ⊇ Set(1:3)
ERROR: UndefVarError: ⊇ not defined

Comparaisons en chaîne

Plusieurs opérateurs de comparaison utilisés ensemble sont chaînés, comme s'ils étaient connectés via l' opérateur && . Cela peut être utile pour des chaînes de comparaison lisibles et mathématiquement concises, telles que

# 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

Cependant, il existe une différence importante entre a > b > c et a > b && b > c ; dans ce dernier cas, le terme b est évalué deux fois. Cela n'a pas beaucoup d'importance pour les vieux symboles simples, mais pourrait avoir de l'importance si les termes eux-mêmes ont des effets secondaires. Par exemple,

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

Examinons de plus près les comparaisons chaînées et leur fonctionnement en observant comment elles sont analysées et abaissées en expressions . Tout d'abord, considérons la simple comparaison, que nous pouvons voir est juste un appel de fonction simple:

julia> dump(:(a > b))
Expr
  head: Symbol call
  args: Array{Any}((3,))
    1: Symbol >
    2: Symbol a
    3: Symbol b
  typ: Any

Maintenant, si nous enchaînons la comparaison, nous remarquons que l'analyse a changé:

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

Après l'analyse, l'expression est ensuite abaissée à sa forme finale:

julia> expand(:(a > b >= c))
:(begin 
        unless a > b goto 3
        return b >= c
        3: 
        return false
    end)

et on remarque en effet que c'est la même chose que pour a > b && b >= c :

julia> expand(:(a > b && b >= c))
:(begin 
        unless a > b goto 3
        return b >= c
        3: 
        return false
    end)

Nombres ordinaux

Nous examinerons comment implémenter des comparaisons personnalisées en implémentant un type personnalisé, des nombres ordinaux . Pour simplifier l'implémentation, nous allons nous concentrer sur un petit sous-ensemble de ces nombres: tous les nombres ordinaux jusqu'à mais n'incluant pas ε₀. Notre implémentation est axée sur la simplicité et non sur la rapidité. Cependant, l'implémentation n'est pas lente non plus.

Nous stockons les nombres ordinaux par leur forme normale de Cantor . Parce que l'arithmétique ordinale n'est pas commutative, nous prendrons la convention commune de stocker d'abord les termes les plus significatifs.

immutable OrdinalNumber <: Number
    βs::Vector{OrdinalNumber}
    cs::Vector{Int}
end

Comme la forme normale de Cantor est unique, nous pouvons tester l’égalité simplement par l’égalité récursive:

0.5.0

Dans la version v0.5, il existe une très bonne syntaxe pour le faire de manière compacte:

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

Sinon, définissez la fonction comme il est plus typique:

import Base: ==
==(α::OrdinalNumber, β::OrdinalNumber) = α.βs == β.βs && α.cs == β.cs

Pour finir notre commande, car ce type a une commande totale, nous devrions surcharger la fonction 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

Pour tester notre ordre, nous pouvons créer des méthodes pour faire des nombres ordinaux. Zéro, bien sûr, est obtenu en n’ayant pas de termes dans la forme normale de Cantor:

const ORDINAL_ZERO = OrdinalNumber([], [])
Base.zero(::Type{OrdinalNumber}) = ORDINAL_ZERO

On peut définir une expω pour calculer ω^α , et l'utiliser pour calculer 1 et ω:

expω(α) = OrdinalNumber([α], [1])
const ORDINAL_ONE = expω(ORDINAL_ZERO)
Base.one(::Type{OrdinalNumber}) = ORDINAL_ONE
const ω = expω(ORDINAL_ONE)

Nous avons maintenant une fonction de commande entièrement fonctionnelle sur les nombres ordinaux:

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])

Dans le dernier exemple, nous voyons que l’impression des nombres ordinaux pourrait être meilleure, mais le résultat est comme prévu.

Opérateurs standard

Julia prend en charge un très grand nombre d'opérateurs de comparaison. Ceux-ci inclus

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

Tous n'ont pas de définition dans la bibliothèque de Base standard. Cependant, ils sont disponibles pour d'autres packages à définir et à utiliser selon les besoins.

Dans un usage quotidien, la plupart de ces opérateurs de comparaison ne sont pas pertinents. Les plus courantes sont les fonctions mathématiques standard pour la commande; voir la section Syntaxe pour une liste.

Comme la plupart des opérateurs de Julia, les opérateurs de comparaison sont des fonctions et peuvent être appelés comme fonctions. Par exemple, (<)(1, 2) est identique à 1 < 2 .

Utiliser ==, === et isequal

Il y a trois opérateurs d'égalité: == , === et isequal . (Le dernier n'est pas vraiment un opérateur, mais c'est une fonction et tous les opérateurs sont des fonctions.)

Quand utiliser ==

== est une valeur d' égalité. Il renvoie true lorsque deux objets représentent, dans leur état actuel, la même valeur.

Par exemple, il est évident que

julia> 1 == 1
true

mais de plus

julia> 1 == 1.0
true

julia> 1 == 1.0 + 0.0im
true

julia> 1 == 1//1
true

Les côtés droits de chaque égalité ci-dessus sont d'un type différent, mais ils représentent toujours la même valeur.

Pour les objets mutables, comme les tableaux , == compare leur valeur actuelle.

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

La plupart du temps, == est le bon choix.

Quand utiliser ===

=== est une opération beaucoup plus stricte que == . Au lieu d’égalité de valeur, elle mesure l’égalité. Deux objets sont égaux s'ils ne peuvent pas être distingués les uns des autres par le programme lui-même. Ainsi nous avons

julia> 1 === 1
true

comme il n'y a aucun moyen de distinguer un 1 d'un autre 1 . Mais

julia> 1 === 1.0
false

car bien que 1 et 1.0 aient la même valeur, ils sont de types différents et le programme peut donc les distinguer.

En outre,

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

ce qui peut paraître surprenant au premier abord! Comment le programme pourrait-il distinguer les deux vecteurs A et B ? Comme les vecteurs sont mutables, ils pourraient modifier A , et se comporter différemment de B Mais peu importe comment cela modifie A , A se comportera toujours de la même manière que A lui-même. Donc, A est égal à A , mais pas égal à B

Continuant dans cette voie, observez

julia> C = A
3-element Array{Int64,1}:
 1
 2
 3

julia> A === C
true

En assignant A à C , on dit que C a un alias A C'est-à-dire que c'est devenu juste un autre nom pour A Toute modification apportée à A sera observée par C également. Par conséquent, il n'y a aucun moyen de faire la différence entre A et C , donc ils sont égaux.

Quand faut-il utiliser isequal

La différence entre == et isequal est très subtile. La plus grande différence réside dans la gestion des nombres à virgule flottante:

julia> NaN == NaN
false

Ce résultat, probablement surprenant, est défini par la norme IEEE pour les types à virgule flottante (IEEE-754). Mais cela n'est pas utile dans certains cas, comme le tri. isequal est fourni pour ces cas:

julia> isequal(NaN, NaN)
true

D'un autre côté du spectre, == traite le zéro négatif de l'IEEE et le zéro positif comme la même valeur (également spécifiée par IEEE-754). Ces valeurs ont cependant des représentations distinctes en mémoire.

julia> 0.0
0.0

julia> -0.0
-0.0

julia> 0.0 == -0.0
true

Toujours à des fins de tri, isequal distingue.

julia> isequal(0.0, -0.0)
false


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow