web-dev-qa-db-fra.com

Pas égal à ceci OR celui de 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

Y a-t-il un moyen de faire cela?

18
Ian

Votre problème provient d'une mauvaise compréhension de l'opérateur or qui est commun aux personnes apprenant 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 j'entrerai dans un peu plus de détails sur la raison pour laquelle votre tentative de solution ne fonctionne pas.

Lorsque vous lisez x ~=(0 or 1) ou x ~= 0 or 1, Il est naturel d'analyser cela comme vous le feriez pour la phrase "x n'est pas égal à zéro ou un". Dans la compréhension ordinaire de cette déclaration, "x" est le sujet, "n'est pas égal à" est le prédicat ou l'expression verbale, et "zéro ou un" est l'objet, un ensemble de possibilités jointes par une conjonction. Vous appliquez le sujet avec le verbe à chaque élément de l'ensemble.

Cependant, Lua n'analyse pas cela en se basant sur les règles de la grammaire anglaise, il l'analyse en comparaisons binaires de deux éléments en fonction de son ordre de fonctionnement. Chaque opérateur a un précédence qui détermine l'ordre dans lequel il sera évalué. or a une priorité inférieure à ~=, tout comme l'addition en mathématiques a une priorité inférieure à la multiplication. Tout a une priorité inférieure aux parenthèses.

Par conséquent, lors de l'évaluation de x ~=(0 or 1), l'interpréteur calculera d'abord 0 or 1 (À cause des parenthèses) puis x ~= Le résultat du premier calcul, et dans le second Par exemple, il calculera x ~= 0 puis appliquera 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 retourne son deuxième argument". opérateur relationnel ~= est l'inverse de l'opérateur d'égalité ==; il renvoie vrai si ses arguments sont de types différents (x est un nombre, n'est-ce pas?), et compare autrement ses arguments normalement.

En utilisant ces règles, x ~=(0 or 1) se décomposera en x ~= 0 (Après avoir appliqué l'opérateur or) et cela retournera 'true' si x est différent de 0, y compris 1, ce qui n'est pas souhaitable. L'autre forme, x ~= 0 or 1 Évaluera d'abord x ~= 0 (Qui peut retourner vrai ou faux, selon la valeur de x). Ensuite, il se décomposera en false or 1 Ou true or 1. Dans le premier cas, l'instruction renverra 1, Et dans le second cas, l'instruction renverra true. Étant donné que les structures de contrôle dans Lua ne considèrent que nil et false comme faux, et tout le reste comme étant vrai, cela entrera toujours l'instruction if, ce qui n'est pas ce que vous voulez non plus.

Il n'y a aucun moyen d'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 une par une. Il y a quelques façons de le faire. La manière la plus simple consiste à utiliser lois de De Morgan pour exprimer la déclaration "pas un ou zéro" (qui ne peut pas être évaluée avec des opérateurs binaires) comme "pas un et pas zéro", ce 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

Vous pouvez également 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, puis tester que x était 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 avez compris l'explication ci-dessus, vous devriez maintenant être en mesure d'expliquer pourquoi je n'ai pas écrit 0 <= x <= 1, Et ce que cette expression erronée retournerait!

49
Kevin Vermeer

Pour tester seulement deux valeurs, je ferais 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 plus de deux valeurs, je bourrerais vos choix dans un tableau agissant comme un ensemble, comme ceci:

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
9
spirulence

x ~= 0 or 1 Est identique à ((x ~= 0) or 1)

x ~=(0 or 1) est identique à (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 )
4
Larry Battle