DEV Community

Alan Matthew
Alan Matthew

Posted on

Truth Tables for Developers: Build One in Python (and Verify Boolean Logic Fast)

Boolean logic shows up everywhere: if conditions, access-control rules, query filters, circuit design, SAT solvers. Truth tables are the simplest way to check that an expression does what you think it does.

This post covers the core idea, the one operator that causes most mistakes, and a small Python script you can reuse.

What a truth table is

A truth table lists every possible True/False assignment for your variables and the result of your expression for each one. With n variables you get 2^n rows, so 3 variables is 8 rows and 8 variables is 256. That growth is why you stop doing this by hand fairly quickly.

The operators

Operator Meaning False when
A AND B both must be true either is false
A OR B at least one true (inclusive) both false
NOT A inverts A is true
A XOR B exactly one true both the same
A -> B material conditional A true and B false
A <-> B biconditional values differ

The one that trips everyone: implication

A -> B is false in exactly one case: A is true and B is false. If A is false, the whole thing is true regardless of B (vacuous truth).

A B A → B
T T T
T F F
F T T
F F T

This is not a quirk. It's what makes the contrapositive valid: A -> B is equivalent to NOT B -> NOT A. It's also why A -> B is equivalent to (NOT A) OR B, which is how you'd write it in most programming languages.

A truth table generator in Python

from itertools import product

def truth_table(expr, variables):
    print(*variables, "|", expr)
    for values in product([True, False], repeat=len(variables)):
        env = dict(zip(variables, values))
        result = eval(expr, {}, env)  # fine for your own input, never for untrusted strings
        print(*[int(v) for v in values], "|", int(result))

truth_table("(not a) or b", ["a", "b"])
Enter fullscreen mode Exit fullscreen mode

Output:

a b | (not a) or b
1 1 | 1
1 0 | 0
0 1 | 1
0 0 | 1
Enter fullscreen mode Exit fullscreen mode

That's the implication table from above. Python has no implication operator, so (not a) or b stands in for it.

Checking logical equivalence

Two expressions are logically equivalent if they produce the same output for every assignment:

def equivalent(expr1, expr2, variables):
    for values in product([True, False], repeat=len(variables)):
        env = dict(zip(variables, values))
        if eval(expr1, {}, env) != eval(expr2, {}, env):
            return False
    return True

# De Morgan's law
print(equivalent("not (a and b)", "(not a) or (not b)", ["a", "b"]))  # True

# Common mistake: not (a and b) is NOT the same as (not a) and (not b)
print(equivalent("not (a and b)", "(not a) and (not b)", ["a", "b"]))  # False
Enter fullscreen mode Exit fullscreen mode

The second check is a good test of whether you've internalized De Morgan's laws. Refactoring a condition by "distributing the not" and getting it wrong is a classic source of bugs.

Identities worth knowing

  • De Morgan: NOT (P AND Q) ≡ (NOT P) OR (NOT Q), and NOT (P OR Q) ≡ (NOT P) AND (NOT Q)
  • Material implication: P -> Q ≡ (NOT P) OR Q
  • Contrapositive: P -> Q ≡ NOT Q -> NOT P
  • Double negation: NOT NOT P ≡ P
  • Absorption: P OR (P AND Q) ≡ P

Classifying expressions

Once you can enumerate every row, you can classify any expression:

  • Tautology: true for every assignment (P OR NOT P)
  • Contradiction: false for every assignment (P AND NOT P)
  • Contingency: true for some, false for others

Spotting a tautology or contradiction inside a real condition usually means dead code or a logic bug.

If you'd rather not write the script

I built a free browser-based generator that does this with a proper parser instead of eval. It supports up to 8 variables, shows intermediate sub-expression columns, flags tautologies and contradictions, has an equivalence checker, and exports CSV. It runs entirely client-side, so nothing is sent to a server:

👉 Truth Table Generator

Disclosure: this tool is hosted on my own site.

If you spot a precedence or parsing edge case, let me know in the comments. Operator precedence in the tool is NOT > AND > XOR > OR > IMPLIES > EQUIV.

Top comments (0)