web-dev-qa-db-ja.com

等しくないOR Luaのそれ

変数がこれまたはそれと等しくないことを確認しようとしています。次のコードを使用してみましたが、どちらも機能しません。

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

これを行う方法はありますか?

18
Ian

あなたの問題は、このようなプログラミング言語を学習している人々に共通するor演算子の誤解に起因しています。はい、差し迫った問題は _x ~= 0 and x ~= 1_ と書くことで解決できますが、試みた解決策が機能しない理由についてもう少し詳しく説明します。

x ~=(0 or 1)または_x ~= 0 or 1_を読むとき、「xがゼロまたは1に等しくない」という文のようにこれを解析するのが自然です。その文の通常の理解では、「x」は主語、「等しくない」は述語または動詞句、「ゼロまたは1」は接続詞によって結合された可能性の集合であるオブジェクトです。動詞を含む件名をセット内の各アイテムに適用します。

ただし、Luaは英語の文法の規則に基づいてこれを解析するのではなく、操作の順序に基づいて2つの要素のバイナリ比較で解析します。各演算子には、評価される順序を決定する precedence があります。数学の加算が乗算よりも優先順位が低いのと同様に、orの優先順位は_~=_よりも低くなっています。すべての優先順位は括弧よりも低くなっています。

その結果、x ~=(0 or 1)を評価するとき、インタープリターは最初に_0 or 1_(括弧があるため)を計算し、次に_x ~=_を最初の計算の結果に、そして2番目の例では、 _x ~= 0_を計算し、その計算結果を_or 1_に適用します。

論理演算子or "この値がnilおよびfalseと異なる場合、最初の引数を返します。それ以外の場合、または2番目の引数を返します"。 関係演算子_~=_ は、等価演算子_==_の逆です。引数が異なるタイプ(xisである場合はtrue)を返し、そうでない場合は通常どおり引数を比較します。

これらの規則を使用すると、x ~=(0 or 1)は_x ~= 0_に分解され(or演算子を適用した後)、xが0以外の場合(1を含む)、 'true'を返します。望ましくない。もう1つの形式_x ~= 0 or 1_は、最初に_x ~= 0_を評価します(xの値に応じてtrueまたはfalseを返す場合があります)。次に、_false or 1_または_true or 1_のいずれかに分解されます。最初の場合、ステートメントは_1_を返し、2番目の場合、ステートメントはtrueを返します。 Luaの制御構造はnilfalseのみをfalseとみなし、他のすべてはtrueとみなすため、これは常にifステートメントを入力しますが、これはあなたが望むものではありませんどちらか。

プログラミング言語で提供されているようなバイナリ演算子を使用して、単一の変数を値のリストと比較する方法はありません。代わりに、変数と各値を1つずつ比較する必要があります。これを行うにはいくつかの方法があります。最も簡単な方法は De Morganの法則 を使用して、ステートメント「not one or zero」(二項演算子では評価できない)を「not one and not zero」として表現することです。二項演算子で書かれた:

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

または、ループを使用してこれらの値を確認できます。

_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
_

最後に、関係演算子を使用して範囲をチェックし、xが範囲内の整数であることをテストできます(0.5は必要ありませんか?)

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

_x >= 0 and x <= 1_と書いたことに注意してください。上記の説明を理解したら、なぜ_0 <= x <= 1_を記述しなかったのか、この誤った式が何を返すのかを説明できるはずです!

49
Kevin Vermeer

2つの値のみをテストするには、個人的にこれを行います。

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

3つ以上の値に対してテストする必要がある場合は、次のように、セットのように振る舞うテーブルに選択肢を詰めます。

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_は_((x ~= 0) or 1)_と同じです

x ~=(0 or 1)は_(x ~= 0)_と同じです。

代わりにこのようなものを試してください。

_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