XOR construido con AND, OR y NOT
A XOR B comparado con (A AND NOT B) OR (NOT A AND B), el o exclusivo construido con AND, OR y NOT. La equivalencia se cumple en las cuatro filas, y la misma fórmula es la que produce el conversor por eliminación de XOR.
El o exclusivo es verdadero cuando las entradas difieren. Escrito con los operadores básicos son dos casos: A sin B, o B sin A. La lectura del motor de A XOR B dice que exclusive_or es verdadero exactamente cuando exactamente uno entre A y B es verdadero, no ambos. En la tabla de cuatro filas la salida es verdadera en las filas 1 y 2, Σm(1, 2), las dos filas en que las entradas difieren, y la forma construida tiene la misma columna.
La equivalencia se cumple: exclusive_or y built coinciden en todas las filas. El XOR no es tautología, contraejemplo A = FALSO, B = FALSO; satisfacible, testigo A = FALSO, B = VERDADERO. El simplificador no encontró ninguna ley que acorte el único operador. El conversor a formas normales aplica una eliminación de XOR y produce la segunda fórmula como FND, (A AND NOT B) OR (NOT A AND B), y (A OR B) AND (NOT A OR NOT B) como FNC, cuatro literales cada una. El mapa dibuja dos grupos de una celda, dos implicantes primos, y deriva los mismos términos. Compuertas: 5 NAND, 11 NOR.
La construcción importa allí donde XOR no es una primitiva: SQL no tiene operador XOR en la mayoría de los dialectos, algunos lenguajes de reglas no tienen ninguno, y las bibliotecas de hardware antiguas lo construyen con NAND. El lado de la FNC, «al menos uno y no ambos», es la versión que la gente escribe en los validadores. Lo que hay que vigilar es que el XOR de más de dos entradas es paridad, no «exactamente uno»; las páginas de tres entradas muestran dónde se separan. Para dos entradas las cuatro filas lo resuelven todo.
exclusive_or := A XOR B · salidabuilt := (A AND NOT B) OR (NOT A AND B) · salida
Comprobaciones exactas
Tabla de verdad (4 filas)
| # | A | B | exclusive_or | built |
|---|---|---|---|---|
| 0 | FALSO | FALSO | FALSO | FALSO |
| 1 | FALSO | VERDADERO | VERDADERO | VERDADERO |
| 2 | VERDADERO | FALSO | VERDADERO | VERDADERO |
| 3 | VERDADERO | VERDADERO | FALSO | FALSO |
Lectura en lenguaje claro
Principianteexclusive_or es verdadero exactamente cuando exactamente uno entre A y B es verdadero (no ambos).
En todos los demás casos, exclusive_or es falso.
Sobre los operadores:
- XOR (O exclusivo) es verdadero cuando exactamente una de sus dos partes es verdadera.
Intermedioexclusive_or es verdadero exactamente cuando exactamente uno entre A y B es verdadero (no ambos).
En todos los demás casos, exclusive_or es falso.
Avanzadoexclusive_or es verdadero exactamente cuando exactamente uno entre A y B es verdadero (no ambos) [disyunción exclusiva ⊕].
En todos los demás casos, exclusive_or es falso.
Notación formal: A ⊕ B
Diagrama lógico
Simplificación paso a paso
El motor no encontró ninguna ley que acorte esta expresión; ya es tan corta como sus leyes de reescritura permiten.
A XOR B
Mapa de Karnaugh
- celdas m1
NOT A AND B - celdas m2
A AND NOT B
Mintérminos y maxtérminos
exclusive_or(A, B) = Σm(1, 2)exclusive_or(A, B) = ΠM(0, 3)Orden de variables: A, B · 4 filas
Formas normales
Forma normal conjuntiva (FNC)
(A OR B) AND (NOT A OR NOT B)2 cláusulas, 4 literales · complete · Eliminación de XOR ×1
Forma normal disyuntiva (FND)
(A AND NOT B) OR (NOT A AND B)2 términos, 4 literales · complete · Eliminación de XOR ×1
Solo NAND, solo NOR
Forma solo con NAND
NAND(NAND(A, NAND(B, B)), NAND(NAND(A, A), B))5 compuertas · equivalencia verificada en todas las filas
Forma solo con NOR
NOR(NOR(NOR(NOR(A, A), B), NOR(A, NOR(B, B))), NOR(NOR(NOR(A, A), B), NOR(A, NOR(B, B))))11 compuertas · equivalencia verificada en todas las filas
La misma regla como código
Python
# -*- coding: utf-8 -*-
# Generated by Tangibool (tangibool.python/1). Do not edit by hand; regenerate from the source revision.
# Model: not stated
# Source revision: reference
# Interpretation status: not stated
"""Tangibool evaluator (decision model).
Generated deterministically from the validated Boolean model; it evaluates exactly that
model. It does not establish that the model is a complete, legal, or safe statement of a
real-world rule, and evaluating examples does not verify the rule.
Source revision: reference
Interpretation status: not stated
Exporter: 1.0.0 (format tangibool.python/1; engine 1.0.0; semantics tangibool-semantics/1)
Logic digest: d70f2f95f330ca533a9d640cbdeb5596a64c385413663e7ce16ae66eac0c83fe
Assumptions digest: d58ee1ad38e23e5093e4baa1047b5ae70d6972e08f555e34ac3fa16df63c4a78
Inputs (dict keys, declared order) and generated parameter names:
'A' -> input_A
'B' -> input_B
Outputs (declared order) and their functions:
'exclusive_or' -> output_exclusive_or(inputs)
'built' -> output_built(inputs)
Assumptions (the declared scope, checked by in_scope(inputs)):
none; every complete assignment is in scope.
Input contract:
Every required input must be exactly True or False (type(value) is bool). Missing
inputs, None, strings, integers (including 0 and 1), and keys that are not declared
inputs raise InputError before anything is evaluated, including inputs that a
short-circuiting operator would never read. Results are always bool.
Scope:
Decision functions raise OutOfScopeError when the inputs violate an assumption; an
out-of-scope assignment is never turned into a False result. Pass check_scope=False
to evaluate without the scope check, and use in_scope(inputs) to test it separately.
Usage:
import tangibool_model as model
model.evaluate({'A': False, 'B': False})
# -> {'exclusive_or': False, 'built': False}
model.output_exclusive_or({'A': False, 'B': False})
# -> False
model.evaluate({'A': 1, 'B': False})
# raises InputError: 1 is an int, not a bool
"""
import collections.abc as _abc
from typing import Dict, Mapping, Tuple
__all__ = [
"MODEL_INFO",
"IDENTIFIER_MAP",
"INPUT_NAMES",
"OUTPUT_NAMES",
"ASSUMPTIONS",
"InputError",
"OutOfScopeError",
"minterm_index",
"in_scope",
"evaluate",
"output_exclusive_or",
"output_built",
]
MODEL_INFO = {
"format": "tangibool.python/1",
"mode": "decision",
"model": None,
"revision": "reference",
"interpretation": None,
"exporter": "1.0.0",
"engine_version": "1.0.0",
"semantics_version": "tangibool-semantics/1",
"logic_digest": "d70f2f95f330ca533a9d640cbdeb5596a64c385413663e7ce16ae66eac0c83fe",
"assumptions_digest": "d58ee1ad38e23e5093e4baa1047b5ae70d6972e08f555e34ac3fa16df63c4a78",
"primary_output": "exclusive_or",
"unused_inputs": (),
"subcircuits": (),
}
# Stable ID -> generated identifier (reversible mapping; names are exact, escaped strings).
IDENTIFIER_MAP = {
"v_99100b359724": {"kind": "input", "name": "A", "identifier": "input_A"},
"v_c68d07688070": {"kind": "input", "name": "B", "identifier": "input_B"},
"f_5bae8c066699": {"kind": "output", "name": "exclusive_or", "identifier": "output_exclusive_or"},
"f_41d4622fbdf2": {"kind": "output", "name": "built", "identifier": "output_built"},
}
INPUT_NAMES = ("A", "B")
OUTPUT_NAMES = ("exclusive_or", "built")
ASSUMPTIONS = ()
_DECLARED_INPUTS = frozenset(INPUT_NAMES)
_SCOPE_INPUTS = ()
_ASSUMPTION_FORMULAS = {entry["name"]: entry["formula"] for entry in ASSUMPTIONS}
class InputError(ValueError):
"""Raised when inputs are missing, undeclared, or not exactly True/False.
Every required input must satisfy type(value) is bool. Missing inputs, None, strings,
integers (including 0 and 1), and keys that are not declared inputs are rejected before
anything is evaluated. A missing input is never treated as False. The individual problems
are listed in the problems attribute.
"""
def __init__(self, problems):
self.problems = tuple(problems)
super().__init__("Invalid inputs: " + "; ".join(self.problems))
class OutOfScopeError(ValueError):
"""Raised when the inputs violate the model's assumptions (its declared scope).
Outside its assumptions the rule has no decision: this error is never a False result.
The names of the violated assumptions are in the violated attribute.
"""
def __init__(self, violated):
self.violated = tuple(violated)
details = ", ".join(name + " (" + _ASSUMPTION_FORMULAS.get(name, "?") + ")" for name in self.violated)
super().__init__(
"Out of scope: the inputs violate "
+ ("assumption " if len(self.violated) == 1 else "assumptions ")
+ details
+ ". The rule has no decision outside its assumptions; this is not a False result."
)
def _short_repr(value: object) -> str:
text = repr(value)
return text if len(text) <= 60 else text[:57] + "..."
def _checked_inputs(inputs: Mapping[str, bool], required: Tuple[str, ...], check_scope: bool) -> Dict[str, bool]:
"""Validate inputs strictly before anything is evaluated and return a plain copy."""
if type(check_scope) is not bool:
raise TypeError("check_scope must be True or False")
if not isinstance(inputs, _abc.Mapping):
raise InputError(["inputs must be a mapping from input names to True/False, got " + type(inputs).__name__])
problems = []
for key in inputs:
if type(key) is not str or key not in _DECLARED_INPUTS:
declared = ", ".join(repr(name) for name in INPUT_NAMES) or "none"
problems.append("undeclared input " + _short_repr(key) + " (declared inputs: " + declared + ")")
needed = tuple(required) + (_SCOPE_INPUTS if check_scope else ())
for name in needed:
if name not in inputs:
problems.append("missing required input " + repr(name))
for key, value in inputs.items():
if type(key) is str and key in _DECLARED_INPUTS and type(value) is not bool:
problems.append(
"input " + repr(key) + " must be True or False (type bool), got "
+ type(value).__name__ + " " + _short_repr(value)
)
if problems:
raise InputError(list(dict.fromkeys(problems)))
return dict(inputs.items())
def _require_bool_args(function: str, pairs: Tuple[Tuple[str, object], ...]) -> None:
problems = [
"argument " + repr(name) + " of " + function + " must be True or False (type bool), got "
+ type(value).__name__ + " " + _short_repr(value)
for name, value in pairs
if type(value) is not bool
]
if problems:
raise InputError(problems)
def minterm_index(*values: bool) -> int:
"""Row index of an assignment over a declared variable order.
The first value is the most significant bit, so all-False is row 0. Used for indexed
minterm (sum) and maxterm (product) forms.
"""
index = 0
for value in values:
if type(value) is not bool:
raise InputError(["minterm_index() takes True/False values, got " + type(value).__name__ + " " + _short_repr(value)])
index = index * 2 + (1 if value else 0)
return index
def _scope_values(values: Dict[str, bool]) -> Tuple[Tuple[str, bool], ...]:
"""Value of every enabled, confirmed assumption for validated inputs, in declared order."""
return ()
def _require_in_scope(values: Dict[str, bool]) -> None:
violated = tuple(name for name, holds in _scope_values(values) if not holds)
if violated:
raise OutOfScopeError(violated)
def in_scope(inputs: Mapping[str, bool]) -> bool:
"""True when the inputs satisfy every assumption (the model's declared scope).
Requires the inputs the assumptions read; raises InputError for invalid inputs.
"""
values = _checked_inputs(inputs, (), True)
return all(holds for _, holds in _scope_values(values))
# ---- Formula bodies (inputs are validated by the public functions below) ----
def _compute_output_exclusive_or(input_A: bool, input_B: bool) -> bool:
"""Decision output 'exclusive_or': A XOR B"""
return input_A != input_B
def _compute_output_built(input_A: bool, input_B: bool) -> bool:
"""Decision output 'built': (A AND NOT B) OR (NOT A AND B)"""
return (input_A and (not input_B)) or ((not input_A) and input_B)
# ---- Public API ----
def output_exclusive_or(inputs: Mapping[str, bool], *, check_scope: bool = True) -> bool:
"""Decision output 'exclusive_or' (stable ID f_5bae8c066699).
'exclusive_or' := A XOR B
Required inputs: 'A', 'B'.
Raises InputError for missing, undeclared, or non-bool inputs, and OutOfScopeError
when check_scope is True and the inputs violate an assumption.
"""
values = _checked_inputs(inputs, ("A", "B"), check_scope)
if check_scope:
_require_in_scope(values)
output_exclusive_or_value = _compute_output_exclusive_or(values["A"], values["B"])
return output_exclusive_or_value
def output_built(inputs: Mapping[str, bool], *, check_scope: bool = True) -> bool:
"""Decision output 'built' (stable ID f_41d4622fbdf2).
'built' := (A AND NOT B) OR (NOT A AND B)
Required inputs: 'A', 'B'.
Raises InputError for missing, undeclared, or non-bool inputs, and OutOfScopeError
when check_scope is True and the inputs violate an assumption.
"""
values = _checked_inputs(inputs, ("A", "B"), check_scope)
if check_scope:
_require_in_scope(values)
output_built_value = _compute_output_built(values["A"], values["B"])
return output_built_value
def evaluate(inputs: Mapping[str, bool], *, check_scope: bool = True) -> Dict[str, bool]:
"""Evaluate every output (declared order); each output is computed once.
Required inputs: 'A', 'B'.
Raises InputError for missing, undeclared, or non-bool inputs, and OutOfScopeError
when check_scope is True and the inputs violate an assumption.
"""
values = _checked_inputs(inputs, ("A", "B"), check_scope)
if check_scope:
_require_in_scope(values)
output_exclusive_or_value = _compute_output_exclusive_or(values["A"], values["B"])
output_built_value = _compute_output_built(values["A"], values["B"])
return {
"exclusive_or": output_exclusive_or_value,
"built": output_built_value,
}
PostgreSQL
-- Tangibool PostgreSQL export (tangibool.postgresql/1)
-- Target: PostgreSQL 16 or later with typed boolean inputs; tested with PostgreSQL 18.3 (PGlite 0.5.8).
-- Not a claim of compatibility with other SQL dialects.
-- Model: not stated
-- Source revision: reference
-- Interpretation status: not stated
-- Exporter: 1.0.0 (engine 1.0.0; semantics tangibool-semantics/1)
-- Logic digest: d70f2f95f330ca533a9d640cbdeb5596a64c385413663e7ce16ae66eac0c83fe
-- Assumptions digest: d58ee1ad38e23e5093e4baa1047b5ae70d6972e08f555e34ac3fa16df63c4a78
-- Mode: decision
--
-- Read-only: this file contains only WITH / VALUES / SELECT statements. No DDL, DML,
-- procedures, credentials, network access, or database changes. The expressions are pure
-- Boolean expressions, so their result does not depend on SQL evaluation order.
--
-- NON-NULL INPUT PRECONDITION: NULL is not a truth value of this rule. Every fragment below
-- is defined only when every input column it reads is a non-NULL boolean. The guard template
-- (section 2) marks any NULL input as 'invalid_input' and any row that violates the
-- assumptions as 'out_of_scope', and fills output columns only for 'ok' rows; a NULL in an
-- output column of another row is an envelope marker, not a third truth value. Never wrap
-- the fragments in COALESCE(..., FALSE) or otherwise choose a meaning for unknown inputs.
-- This evaluates the supplied model; it does not show that the model is a complete, legal,
-- or safe statement of a real-world rule.
--
-- Input columns (stable ID: name -> column):
-- v_99100b359724: A -> "in_A"
-- v_c68d07688070: B -> "in_B"
-- Output columns:
-- f_5bae8c066699: exclusive_or -> "out_exclusive_or"
-- f_41d4622fbdf2: built -> "out_built"
-- Assumptions (scope K; exported separately and never folded into an output):
-- none; every complete input row is in scope.
-- ----------------------------------------------------------------------------------------------
-- 1. Expression fragments (parenthesised; non-NULL boolean inputs required)
-- ----------------------------------------------------------------------------------------------
--
-- [out_exclusive_or] output exclusive_or (stable ID f_5bae8c066699)
-- exclusive_or := A XOR B
-- PRECONDITION: "in_A", "in_B" are non-NULL booleans.
-- ("in_A" <> "in_B")
--
-- [out_built] output built (stable ID f_41d4622fbdf2)
-- built := (A AND NOT B) OR (NOT A AND B)
-- PRECONDITION: "in_A", "in_B" are non-NULL booleans.
-- (("in_A" AND (NOT "in_B")) OR ((NOT "in_A") AND "in_B"))
--
-- ----------------------------------------------------------------------------------------------
-- 2. Guard template (read-only SELECT over an inputs list)
-- ----------------------------------------------------------------------------------------------
-- Replace the example rows between the markers with your own rows, or replace the inputs
-- CTE with a SELECT that provides the boolean columns listed in the header. status is
-- 'invalid_input' when any input is NULL, 'out_of_scope' when the assumptions are false, and
-- 'ok' otherwise; output columns are filled only for 'ok' rows (NULL elsewhere is an
-- envelope marker). Assumption columns are shown for rows with complete inputs.
WITH inputs ("row_id", "in_A", "in_B") AS (
-- tangibool:example-rows:begin
VALUES
(1, FALSE, FALSE),
(2, FALSE, TRUE),
(3, TRUE, FALSE),
(4, TRUE, TRUE),
(5, NULL::boolean, FALSE)
-- tangibool:example-rows:end
),
checked AS (
SELECT
inputs.*,
CASE
WHEN "in_A" IS NULL OR "in_B" IS NULL THEN 'invalid_input'
ELSE 'ok'
END AS "status"
FROM inputs
)
SELECT
"row_id",
"in_A",
"in_B",
"status",
CASE WHEN "status" = 'ok' THEN ("in_A" <> "in_B") END AS "out_exclusive_or",
CASE WHEN "status" = 'ok' THEN (("in_A" AND (NOT "in_B")) OR ((NOT "in_A") AND "in_B")) END AS "out_built"
FROM checked
ORDER BY "row_id";
SMT-LIB
; Tangibool SMT-LIB export (tangibool.smtlib/1) ; Profile: SMT-LIB 2.6 Boolean subset (QF_UF): Bool constants, define-fun, let, push/pop, assert, check-sat, echo. ; Tested with Z3 5.1.0 (z3-solver 5.2.0, WebAssembly build). ; Model: not stated ; Source revision: reference ; Interpretation status: not stated ; Exporter: 1.0.0 (engine 1.0.0; semantics tangibool-semantics/1) ; Logic digest: d70f2f95f330ca533a9d640cbdeb5596a64c385413663e7ce16ae66eac0c83fe ; Assumptions digest: d58ee1ad38e23e5093e4baa1047b5ae70d6972e08f555e34ac3fa16df63c4a78 ; Mode: decision ; ; Reading results: each query block states what sat and unsat mean for its question. A sat ; answer comes with a witness or counterexample (ask for it with (get-model) after sat only); ; unsat settles that scoped query and is solver-checked, not an independently checked proof ; certificate; unknown settles nothing. Blocks are scoped with push/pop, so assertions never ; accumulate across questions. This checks the supplied model, not whether it is a complete, ; legal, or safe statement of a real-world rule. ; ; Symbols (stable ID: name -> symbol): ; v_99100b359724: A -> in_A ; v_c68d07688070: B -> in_B ; f_5bae8c066699: exclusive_or -> out_exclusive_or ; f_41d4622fbdf2: built -> out_built (set-option :produce-models true) (set-info :smt-lib-version 2.6) (set-logic QF_UF) ; ---- Inputs (declared order) (declare-const in_A Bool) ; A (declare-const in_B Bool) ; B ; ---- Outputs (dependencies first) ; output exclusive_or (stable ID f_5bae8c066699): A XOR B (define-fun out_exclusive_or () Bool (xor in_A in_B)) ; output built (stable ID f_41d4622fbdf2): (A AND NOT B) OR (NOT A AND B) (define-fun out_built () Bool (or (and in_A (not in_B)) (and (not in_A) in_B))) ; ---- Assumptions (the scope K; never folded into an output) ; K: conjunction of the enabled, confirmed assumptions (true when there are none) (define-fun K () Bool true) ; ---- Definitions only: nothing is asserted and no check is run. ; Add (assert ...) and (check-sat) inside (push 1) ... (pop 1) to ask a question.
LaTeX
exclusive_or = A \oplus B
built = \left(A \cdot \overline{B}\right) + \left(\overline{A} \cdot B\right)El error habitual
Escribir el o exclusivo como (A OR B) AND NOT (A AND B) y tratarlo como una función distinta. Es la FNC que deriva el conversor, disfrazada: De Morgan convierte NOT (A AND B) en NOT A OR NOT B. El comprobador de equivalencia confirma que coincide con A XOR B en las cuatro filas.
Preguntas
¿Cuál de las dos formas usa el motor internamente?
El operador XOR se conserva tal como se escribió en el modelo, la tabla de verdad y el diagrama. Los conversores lo reescriben por eliminación de XOR solo cuando necesitan una forma AND-OR, y registran esa ley como paso para que veas de dónde salen los cuatro literales.
Relacionado
Operadores y compuertas
- Compuerta NOT (inversor): tabla de verdad, símbolo y el operador NOT
- Compuerta AND (puerta Y): tabla de verdad de 2, 3 y 4 entradas, símbolo y expresión
- Compuerta OR (puerta O): tabla de verdad de 2, 3 y 4 entradas
- Compuerta XOR: tabla de verdad de 2, 3 y 4 entradas (paridad impar)
Herramientas
- Generador de tablas de verdad: cualquier expresión booleana, hasta 12 variables, con columnas intermedias
- Calculadora y simplificador de álgebra de Boole paso a paso (cada ley nombrada y verificada)
- Solucionador de mapas de Karnaugh: de 2 a 4 variables, agrupaciones, SOP y POS
Véase también
- Compuerta XOR: tabla de verdad de 2, 3 y 4 entradas (paridad impar)
- Eliminación de XOR: A ⊕ B = A·B' + A'·B
- XNOR construido con AND, OR y NOT
- XOR con cuatro compuertas NAND, equivalencia verificada
- Semisumador, suma: A XOR B
- O inclusivo frente a exclusivo: «o ambos» es el valor por defecto
Ejemplos resueltos
Generado a partir del motor de Tangibool, semántica tangibool-semantics/1, motor 1.0.0, compilación . Cada tabla, mapa, simplificación y veredicto de estas páginas lo calculó el motor de Tangibool al compilar el sitio, y cada afirmación la volvió a comprobar el mismo verificador exacto que usa la app. Los límites se indican donde aplican. © 2026 Foreranger LTD.