35. Funciones booleanas

Una función booleana recibe valores verdaderos o falsos y produce un único resultado booleano. Describe decisiones, validaciones y el comportamiento de las puertas lógicas que forman los circuitos digitales.

35.1 Introducción

El tema anterior estudió las operaciones del álgebra de Boole. Ahora las usamos para definir funciones: reglas que reciben una combinación de entradas binarias y devuelven un valor binario.

Una condición de un if, una regla de permisos, un filtro de datos y una puerta digital pueden verse como funciones booleanas. La tabla de verdad es su especificación más directa.

35.2 Definición

Una función booleana de n variables es una función cuyo dominio es {0, 1}n y cuyo codominio es {0, 1}:

f: {0, 1}n → {0, 1}.

f(p, q) = p ∧ q es una función de dos variables.
f(p, q, r) = (p ∨ q) ∧ ¬r es una función de tres variables.

El dominio contiene todas las combinaciones posibles de n entradas. Como cada entrada tiene dos valores, hay 2n combinaciones que la función debe definir.

35.3 Tablas de verdad

Una tabla de verdad enumera cada combinación de entradas y el resultado de la función. Para dos variables hay cuatro filas.

pqf(p, q) = p ∧ q
000
010
100
111

La tabla no deja casos implícitos: indica exactamente qué resultado produce la función para cualquier entrada permitida.

35.4 Cuántas funciones booleanas existen

Una función de n variables tiene 2n filas en su tabla. Cada fila puede asignarse independientemente a 0 o 1, por lo que el número de funciones booleanas distintas es:

Número de funciones de n variables = 22n.

n = 1: 22 = 4 funciones.
n = 2: 24 = 16 funciones.
n = 3: 28 = 256 funciones.

El crecimiento es muy rápido. Con cuatro variables ya hay 65 536 funciones posibles, aunque muchas no tienen un nombre especial ni una expresión sencilla.

35.5 Funciones de una variable

Las cuatro funciones booleanas posibles de una variable son la constante falsa, la identidad, la negación y la constante verdadera.

p0p¬p1
00011
10101

Una función constante ignora su entrada. La identidad la conserva y la negación la invierte. Estas operaciones simples se combinan para construir funciones más complejas.

35.6 Funciones binarias habituales

pqANDORXORNANDNOR
0000011
0101110
1001110
1111000

XOR es verdadero cuando exactamente una entrada es verdadera. NAND y NOR son las negaciones de AND y OR, respectivamente; más adelante veremos que cada una de ellas puede construir cualquier función booleana.

35.7 Implementar funciones básicas

const and = (p, q) => p && q;
const or = (p, q) => p || q;
const not = p => !p;
const xor = (p, q) => p !== q;
const nand = (p, q) => !(p && q);
const nor = (p, q) => !(p || q);

console.log(xor(true, false)); // true
console.log(nand(true, true)); // false
console.log(nor(false, false)); // true

La desigualdad estricta entre booleanos implementa XOR porque true !== false y false !== true, mientras que entradas iguales producen false.

35.8 Función mayoría

La función mayoría de tres entradas vale 1 cuando al menos dos de las tres entradas valen 1. Se usa como modelo de votación y como componente de ciertos circuitos.

M(p, q, r) = (p ∧ q) ∨ (p ∧ r) ∨ (q ∧ r).

Si dos o tres entradas son verdaderas, alguno de los productos vale verdadero.

La expresión muestra una forma natural de describir la regla: cada término cubre uno de los pares que basta para obtener mayoría.

35.9 Implementar una regla de mayoría

function mayoria(p, q, r) {
  return (p && q) || (p && r) || (q && r);
}

console.log(mayoria(false, true, true)); // true
console.log(mayoria(false, true, false)); // false

Una alternativa es contar valores verdaderos, pero la expresión booleana comunica directamente la estructura lógica y se traduce de manera inmediata a puertas digitales.

35.10 Equivalencia de funciones

Dos funciones booleanas son iguales si devuelven el mismo valor para cada combinación de entradas. No importa que sus expresiones tengan formas distintas.

f(p, q) = p ∧ (p ∨ q).
g(p, q) = p.

f y g son la misma función booleana,
porque coinciden en sus cuatro filas de verdad.

La equivalencia puede demostrarse con una tabla de verdad o aplicando leyes del álgebra de Boole, como la absorción.

35.11 Generar una tabla de verdad

Para un número pequeño de variables, un programa puede enumerar todas las combinaciones binarias y evaluar una función.

function tablaDeVerdad(cantidadVariables, funcion) {
  const filas = [];
  const total = 2 ** cantidadVariables;

  for (let numero = 0; numero < total; numero++) {
    const entradas = Array.from({ length: cantidadVariables }, (_, indice) => {
      const desplazamiento = cantidadVariables - indice - 1;
      return Boolean((numero >> desplazamiento) & 1);
    });
    filas.push({ entradas, salida: funcion(...entradas) });
  }
  return filas;
}

console.log(tablaDeVerdad(2, xor));

El código interpreta cada número entre 0 y 2n - 1 como una combinación de bits. Es adecuado para tablas pequeñas; para muchas variables, 2n filas crecen demasiado rápido.

35.12 Minterminos

Un mintermino es una conjunción que contiene todas las variables, negando las que valen 0 y dejando sin negar las que valen 1. Cada mintermino vale 1 en exactamente una fila de la tabla.

Para p = 0, q = 1, el mintermino es ¬p ∧ q.

¬p ∧ q solo es verdadero cuando p es falso y q es verdadero.

La suma lógica, es decir OR, de los minterminos correspondientes a las filas donde una función vale 1 produce una representación canónica de la función.

35.13 Forma normal disyuntiva

La forma normal disyuntiva o suma de productos expresa una función como OR de minterminos. Es una forma canónica cuando se incluyen todos los minterminos de las filas con salida 1.

XOR(p, q) vale 1 en 01 y 10.

XOR(p, q) = (¬p ∧ q) ∨ (p ∧ ¬q).

Esta representación siempre existe porque una tabla de verdad enumera todas las entradas. No siempre es la expresión más corta; la simplificación busca reducir términos y variables.

35.14 Maxterminos y forma normal conjuntiva

Un maxtermino es una disyunción que vale 0 en exactamente una fila. La forma normal conjuntiva o producto de sumas usa AND de los maxterminos de las filas donde la función vale 0.

XOR(p, q) vale 0 en 00 y 11.

Para 00: p ∨ q.
Para 11: ¬p ∨ ¬q.

XOR(p, q) = (p ∨ q) ∧ (¬p ∨ ¬q).

Las formas disyuntiva y conjuntiva describen la misma función desde perspectivas complementarias. La primera enumera las entradas aceptadas; la segunda enumera las combinaciones que se deben evitar.

35.15 Simplificación de funciones

Una forma canónica puede tener muchos términos. Las leyes booleanas permiten obtener una expresión equivalente más pequeña.

(p ∧ q) ∨ (p ∧ ¬q)
= p ∧ (q ∨ ¬q)
= p ∧ 1
= p.

Para pocas variables, las tablas de Karnaugh ayudan a visualizar agrupamientos de filas adyacentes. Para expresiones grandes se usan algoritmos de minimización y herramientas de síntesis lógica.

35.16 Funciones funcionalmente completas

Un conjunto de conectivos es funcionalmente completo si permite expresar cualquier función booleana. AND, OR y NOT forman un conjunto completo, pero NAND por sí sola también lo es, al igual que NOR por sí sola.

Con NAND:
¬p = p NAND p.
p ∧ q = ¬(p NAND q).

Al reconstruir NOT y AND, se pueden construir OR y cualquier otra función.

Esta propiedad es importante para la electrónica digital: un circuito puede fabricarse usando una sola familia de puertas universales.

35.17 Composición de funciones

Podemos usar la salida de una función booleana como entrada de otra. Así se construyen expresiones y circuitos de mayor complejidad a partir de componentes pequeños.

f(p, q, r) = AND(OR(p, q), NOT(r)).

En notación algebraica:
f(p, q, r) = (p ∨ q) ∧ ¬r.

En programación, dividir una condición compleja en funciones con nombres claros facilita probarla y reduce el riesgo de confundir la prioridad de los operadores.

35.18 Funciones booleanas y validación

Una validación es una función booleana: recibe datos, evalúa condiciones y responde si son aceptables según una regla. Por ejemplo, una cuenta puede requerir correo válido, contraseña suficiente y aceptación de términos.

function registroValido(correoValido, contrasenaSegura, aceptaTerminos) {
  return correoValido && contrasenaSegura && aceptaTerminos;
}

console.log(registroValido(true, true, true));  // true
console.log(registroValido(true, false, true)); // false

Separar cada predicado permite explicar por qué una entrada no es válida y probar todos los casos relevantes sin repetir la lógica de la regla principal.

35.19 Funciones booleanas y búsqueda

Los filtros de colecciones son predicados: funciones que devuelven un booleano para cada elemento. Combinarlos con AND, OR y NOT construye búsquedas complejas.

const productos = [
  { nombre: "Teclado", enStock: true, precio: 40 },
  { nombre: "Monitor", enStock: false, precio: 180 },
  { nombre: "Mouse", enStock: true, precio: 25 }
];

const visibles = productos.filter(producto =>
  producto.enStock && producto.precio <= 50
);

console.log(visibles); // Teclado y Mouse

La función pasada a filter define formalmente qué elementos pertenecen al resultado. Ajustar un filtro equivale a modificar una función booleana.

35.20 Límites de las tablas de verdad

Las tablas de verdad son exhaustivas, pero su tamaño es exponencial. Con 10 variables hay 1 024 filas; con 20 hay más de un millón.

n variables → 2n combinaciones.

Las tablas son excelentes para pocas entradas.
Para muchas entradas se usan álgebra, pruebas dirigidas, herramientas simbólicas y especificaciones por partes.

La explosión combinatoria explica por qué el diseño de funciones lógicas complejas requiere abstraer, simplificar y verificar propiedades sin enumerar siempre todos los casos.

35.21 Errores frecuentes

  • Confundir XOR con OR inclusivo.
  • Olvidar que una función de n variables tiene 2n combinaciones de entrada.
  • Construir un mintermino sin incluir alguna variable.
  • Invertir las filas usadas para la forma disyuntiva y la conjuntiva.
  • Asumir que dos expresiones parecidas son equivalentes sin comprobarlas.
  • Generar tablas enormes sin considerar el crecimiento exponencial.

35.22 Qué debes recordar y conclusión

  • Una función booleana tiene entradas y salida en {0, 1}.
  • Con n variables hay 2n filas posibles y 22n funciones distintas.
  • Una tabla de verdad especifica completamente una función pequeña.
  • Los minterminos forman una suma de productos; los maxterminos forman un producto de sumas.
  • NAND y NOR son puertas universalmente funcionales.
  • Las funciones booleanas modelan validaciones, filtros, decisiones y circuitos.

Las funciones booleanas convierten reglas lógicas en objetos que se pueden especificar, simplificar, probar y componer. En el próximo tema veremos cómo estas funciones se implementan físicamente mediante circuitos combinacionales.