I have a variable v
in my program, and it may take any value from the set of values
"a", "b", "c", ..., "z"
And my goal is to execute some statement only when v
is not "x"
, "y"
, or "z"
.
I have tried,
for C-like languages (where equality operators compare the actual string values; e.g. c#, javascript, 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 (e.g. plsql)
IF (v != 'x' OR v != 'y' OR v != 'z') THEN
-- the statements I want to be executed
-- if v is neither "x", nor "y", nor "z"
END IF;
The statements inside the if
condition always get executed. Am I doing anything wrong?
Use &&
/AND
/and
, not ||
/OR
/or
:
v != "x" && v != "y" && v != "z"
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
.
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;
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.
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"].includes(v)
python: v not in {"x", "y", "z"}
java-9 (and above): !Set.of("x", "y", "z").contains(v)