Common Boolean logic mistakes and how to catch them
Twenty-five ways a Boolean rule goes wrong, each with the wrong and the right formula side by side, the row where they differ, and the fix.
Most are slips of translation: pushing NOT through AND without flipping it, reading “or” as exclusive, reading “unless” as OR, confusing an implication with its converse, treating “only if” as “if”. Some are slips of notation that the parser catches for you: = and == are not operators, AB is one name and not A AND B, ^ is XOR in most languages, a single & is bitwise. The rest are slips of trust: a vacuous truth that looks like a pass, inconsistent assumptions that make every test pass, a timeout read as success, coverage read as correctness.
Where a pitfall is a pair of formulas, the engine computed both columns and marked the rows where they disagree; the equivalence verdict and the counterexample are the engine's, not a claim. Where a pitfall is a spelling, the page shows exactly what the parser says and the repair it offers.
Each page links to the law that explains the slip and to the lesson that teaches it.
- NOT (A AND B) = NOT A OR NOT B, not NOT A AND NOT B
NOT (A AND B) equals NOT A OR NOT B (“not both”), not NOT A AND NOT B, which equals NOT (A OR B) (“neither”). - “A or B and C”: the grouping ambiguity and how to resolve it
“A or B and C” has two readings, and they are different functions. The parser reads A OR B AND C as A OR (B AND C); the other reading, (A OR B) AND C, differs on two of the eight rows. - XOR of three inputs is odd parity, not “exactly one”
A XOR B XOR C is TRUE when an odd number of inputs are TRUE, so it is TRUE when all three are. “Exactly one of three” is a different function, and the two differ on exactly one row. - A → B does not give B → A
A -> B does not give B -> A. The two implications differ on the rows where exactly one of A and B holds, and the engine's check names A = FALSE, B = TRUE as the counterexample. - Necessary vs sufficient: “only if” is not “if”
“A only if B” makes B necessary for A: A -> B. “A if B” makes B sufficient for A: B -> A. The two formulas differ on two rows, and the one word “only” is the whole difference. - Inclusive vs exclusive or (OR vs XOR), with truth table
Inclusive or (OR) is TRUE when at least one input is TRUE, including when both are; exclusive or (XOR) is TRUE when exactly one is. - “Unless” in a rule: AND NOT, not OR
“Members may enter unless banned” is member AND NOT banned. Written with OR, member OR NOT banned, the rule admits two groups it should not, and the table shows both rows. - “Neither A nor B” is NOT A AND NOT B
“Neither A nor B” means both fail: NOT A AND NOT B, which is NOR(A, B). The common slip, NOT A OR NOT B, is “not both”, and the two differ on the rows where exactly one of A and B holds. - Vacuous truth: a property that holds because nothing satisfies the assumptions
From the premises A and NOT A, anything follows, including B. - Inconsistent assumptions make every test pass
A rule checked under assumptions that cannot all hold passes every test for a bad reason. - “=” is not a Boolean operator: use ↔ or compare the formulas
A = B is not a formula in this language. - AB is one name, not A AND B: implicit multiplication
AB is one name, not A AND B. Textbooks drop the dot in A·B; the parser does not, because a rule's inputs have names like member and banned, and AB must be allowed to be one of them. - ^ means XOR in C, Java and Python, not AND or power
^ is exclusive or in C, Java, JavaScript and Python, a power in Excel and many calculators, and conjunction in some logic texts. - Single & and | are bitwise in most languages
A single & or | is a bitwise operator in C, Java and JavaScript, and in Java it is also a non-short-circuit logical operator. The parser rejects both and offers the word or the doubled symbol. - ~ is bitwise NOT in code, logical NOT in some textbooks
~ is the bitwise complement in C, Java, JavaScript and Python, where ~1 is -2, and the logical NOT in some logic textbooks. The parser rejects ~A and offers NOT, ! or ¬. - Double equals (==) compares values; for logical equivalence use ↔
== compares two values in a program and returns a Boolean. Between two Boolean formulas it computes the biconditional; as a claim that two formulas are equivalent it is a different thing altogether. - != on Booleans is XOR
On two Boolean values, != is exclusive or: TRUE exactly when they differ. The parser rejects A != B and offers XOR, which is the same function under its logical name. - Arrow variants: => and <=> vs → and ↔, which means what
-> and → are implication; <-> and ↔ are the biconditional. The fat arrows => and <=> are rejected, because they mean implication in some tools, a function in JavaScript, and a rewrite step in others. - NULL is not FALSE: three-valued logic in SQL
a OR NOT a is a tautology on two values, and the engine proves it on both rows. In SQL, where a can be NULL, the same expression is NULL, and a WHERE clause drops the row. - An unassigned input is not FALSE: incomplete assignments
An input with no value is not FALSE. Evaluating A AND B with A = TRUE and B unassigned gives no value, and the engine says which input is missing rather than guessing. - “Simplified” is not “minimal”: what a simplifier can promise
The simplifier found no law that shortens (A AND B) OR (A AND NOT B) OR (NOT A AND B), yet the function is A OR B. - A timeout is not a pass: “Not determined” results
When the engine runs out of budget or hits a size limit, it reports “Not determined”, never a pass. - Coverage is not correctness: tests still need expected results
A test suite can cover every input and every branch of a rule and still miss the bug, because coverage measures what the tests touched, not whether the expected results were right. - Confusable names: l, 1, I, O and 0 in variable names
l1 and I1 are different inputs that look the same on screen, and rate and Rate differ only by case. - Precedence differs across languages: not a == b in Python
not a == b is not (a == b) in Python, because comparison binds tighter than not. In C, a & b == c is a & (b == c).
Questions
Which pitfall is the most common?
In rule writing, the De Morgan slip (NOT (A AND B) read as NOT A AND NOT B) and the grouping slip (A OR B AND C read with the wrong grouping). In code, the single ampersand and the caret. The entry-rule example shows a grouping slip that lets a banned member in.
Generated from the Tangibool engine, semantics tangibool-semantics/1, engine 1.0.0, build . Every table, map, simplification and verdict on these pages was computed by the Tangibool engine when the site was built, and every claim was re-checked by the same exact checker the app uses. Limits are stated where they apply. © 2026 Foreranger LTD.