Why non-equality check of one variable against many values always returns true?

前端 未结 3 1253
无人及你
无人及你 2020-11-21 04:27

I have a variable v in my program, and it may take any value from the set of values

\"a\", \"b\", \"c\", ..., \"z\"

A

3条回答
  •  无人及你
    2020-11-21 05:02

    Use &&/AND/and, not ||/OR/or:

    v != "x" && v != "y" && v != "z"
    

    Problem

    If an if block is always executed, the condition for the if block always evaluates to true. The logical expression must be wrong.

    Let us consider v != "x" || v != "y" || v != "z" for each value of v.

    • When v = "x",

      v != "x" becomes "x" != "x", which is false.
      v != "y" becomes "x" != "y", which is true.
      v != "z" becomes "x" != "z", which is true.

      The expression evaluates to false || true || true, which is true.

    • When v = "y", the expression becomes

      "y" != "x" || "y" != "y" || "y" != "z"
      

      or true || false || true, which is true.

    • When v = "z", the expression becomes

      "z" != "x" || "z" != "y" || "z" != "z"
      

      or true || true || false, which is true.

    • For any other value for v, the expression evaluates to true || true || true, which is true.

    Alternatively, consider the truth-table:

           │     A          B          C      │
      v    │  v != "x"   v != "y"   v != "z"  │  A || B || C
    ───────┼──────────────────────────────────┼──────────────
     "x"   │    false      true       true    │     true
     "y"   │    true       false      true    │     true
     "z"   │    true       true       false   │     true
    other  │    true       true       true    │     true
    

    As you can see, your logical expression always evaluates to true.

    Solution

    What you want to do is, find a logical expression that evaluates to true when

    (v is not "x")and(v is not "y")and(v is not "z").

    The correct construction is,

    • for C-like languages (eg. c#, javascript-(may need the strict equality operator !==), php)

      if (v != "x" && v != "y" && v != "z")
      {
          // the statements I want to be executed
          // if v is neither "x", nor "y", nor "z"
      }
      
    • for Pascal-like languages plsql

      IF (v != 'x' AND v != 'y' AND v != 'z') THEN
          -- the statements I want to be executed
          -- if v is neither "x", nor "y", nor "z"
      END IF;
      

    De Morgan's law

    By De Morgan's law, the expression can also be rewritten as (using C-like syntax)

    !(v == "x" || v == "y" || v == "z")
    

    meaning

    not((v is "x")or(v is "y")or(v is "z")).

    This makes the logic a bit more obvious.

    Specific languages

    Some languages have specific constructs for testing membership in sets, or you can use array/list operations.

    • sql: v NOT IN ('x', 'y', 'z')

    • javascript: ["x", "y", "z"].indexOf(v) == -1

    • python: v not in {"x", "y", "z"}

    • java: Arrays.asList("x", "y", "z").contains(v)

    • java-9 (and above): Set.of("x", "y", "z").contains(v)

提交回复
热议问题