Pas égal à ceci ou cela dans Lua

j'essaie de vérifier qu'une variable n'est pas égale à ceci ou cela. J'ai essayé d'utiliser les codes suivants, mais aucun ne fonctionne:

if x ~=(0 or 1) then
    print( "X must be equal to 1 or 0" )
    return
end


if x ~= 0 or 1 then
    print( "X must be equal to 1 or 0" )
    return
end

Est-il possible de faire cela?

17
demandé sur Ian 2012-07-26 01:33:11

3 réponses

Votre problème provient d'une incompréhension de l' or opérateur commun aux gens qui apprennent des langages de programmation comme celui-ci. Oui, votre problème immédiat peut être résolu en écrivant x ~= 0 and x ~= 1, mais je vais entrer dans un peu plus de détails sur la raison pour laquelle votre solution tentée ne fonctionne pas.

Quand vous lisez x ~=(0 or 1) ou x ~= 0 or 1 il est naturel d'analyser ce que vous la phrase "x n'est pas égal à zéro ou à un". Dans la compréhension ordinaire de ce l'énoncé, "x" est le sujet," n'est pas égal à "est la phrase de prédicat ou de verbe, et" zéro ou un " est l'objet, un ensemble de possibilités jointes par une conjonction. Vous appliquez le sujet avec le verbe de chaque élément dans l'ensemble.

cependant, Lua ne l'analyse pas sur la base des règles de la grammaire anglaise, il l'analyse dans des comparaisons binaires de deux éléments basés sur son ordre d'opération. Chaque opérateur a un priorité qui détermine l'ordre dans lequel il sera évaluer. or a une priorité plus faible que ~=, tout comme l'addition en mathématiques a une priorité plus faible que la multiplication. Tout a une priorité plus basse que les parenthèses.

en conséquence, lors de l'évaluation de x ~=(0 or 1), l'interprète d'abord calculer 0 or 1 (à cause des parenthèses) et puis x ~= le résultat du premier calcul, et dans le deuxième exemple, on va calculer x ~= 0 et ensuite appliquer le résultat de ce calcul à or 1.

opérateur logique or "renvoie son premier argument si cette valeur est différente de nil et false; sinon, ou renvoie son second argument". opérateur relationnel ~= est l'inverse de l'opérateur d'égalité ==; il retourne true si ses arguments sont de types différents (x un numéro, c'est ça?), et compare autrement ses arguments normalement.

à l'Aide de ces règles, x ~=(0 or 1) décomposer x ~= 0(après application du or operator) et ceci retournera 'true' si x est autre chose que 0, y compris 1, ce qui est indésirable. L'autre forme, x ~= 0 or 1 allons d'abord évaluer x ~= 0 (qui peut renvoyer true ou false, selon la valeur de x). Ensuite, il se décomposera en un defalse or 1 ou true or 1. Dans le premier cas, la déclaration retournera 1, et dans le second cas, l'instruction return true. Parce que les structures de contrôle en Lua seulement considérer nil et false faux, et rien d'autre pour être vrai, ce sera toujours entrer dans le if déclaration, qui n'est pas ce que vous voulez.

il n'y a aucun moyen que vous puissiez utiliser des opérateurs binaires comme ceux fournis dans les langages de programmation pour comparer une seule variable à une liste de valeurs. Au lieu de cela, vous devez comparer la variable à chaque valeur un par un. Il ya quelques façons de le faire. La façon la plus simple est d'utiliser les lois De De Morgan, pour exprimez la Déclaration "pas un ou zéro" (qui ne peut pas être évalué avec des opérateurs binaires) comme "pas un et pas zéro", qui peut être trivialement écrit avec des opérateurs binaires:

if x ~= 1 and x ~= 0 then
    print( "X must be equal to 1 or 0" )
    return
end

Alternativement, vous pouvez utiliser une boucle pour vérifier ces valeurs:

local x_is_ok = false
for i = 0,1 do 
    if x == i then
        x_is_ok = true
    end
end
if not x_is_ok then
    print( "X must be equal to 1 or 0" )
    return
end

enfin, vous pouvez utiliser des opérateurs relationnels pour vérifier une plage et ensuite tester que x est un entier dans la plage (vous ne voulez pas 0.5, Non?)

if not (x >= 0 and x <= 1 and math.floor(x) == x) then
    print( "X must be equal to 1 or 0" )
    return
end

Notez que j'ai écrit x >= 0 and x <= 1. Si vous compris l'explication ci-dessus, vous devriez maintenant être en mesure d'expliquer pourquoi je n'ai pas écrit 0 <= x <= 1, et qu'est-ce que cette expression erronée reviendrait!

42
répondu Kevin Vermeer 2017-05-23 12:26:14

Pour tester que deux valeurs, je serais personnellement ceci:

if x ~= 0 and x ~= 1 then
    print( "X must be equal to 1 or 0" )
    return
end

si vous avez besoin de tester contre plus de deux valeurs, je remplirais vos choix dans une table agissant comme un ensemble, comme ainsi:

choices = {[0]=true, [1]=true, [3]=true, [5]=true, [7]=true, [11]=true}

if not choices[x] then
    print("x must be in the first six prime numbers")
    return
end
8
répondu spirulence 2012-07-25 21:46:12

x ~= 0 or 1 est le même que ((x ~= 0) or 1)

x ~=(0 or 1) est le même que (x ~= 0).

essayez plutôt quelque chose comme ça.

function isNot0Or1(x)
    return (x ~= 0 and x ~= 1)
end

print( isNot0Or1(-1) == true )
print( isNot0Or1(0) == false )
print( isNot0Or1(1) == false )
3
répondu Larry Battle 2012-07-25 21:53:32