← Midas

El dígito de control no tiene tasa de acierto

Cuando alguien dice «el algoritmo de Verhoeff detecta el 99,7 % de los errores», la cifra suena a propiedad de Verhoeff, como la densidad del plomo. No lo es. Es una propiedad del par (fórmula, modelo de error), y de los dos miembros del par sólo se escribe uno. El otro —el censo de errores de transcripción que Jacobus Verhoeff levantó en 1969 sobre el correo holandés, con gente copiando números a mano— viaja de cita en cita hasta 2026, donde los números se meten con teclado, se leen con escáner y se dictan por teléfono.

Lo primero fue que la fórmula se me rompió en la mano

Antes de sellar hice un piloto: enumerar exhaustivamente la mancha ciega de cada esquema —qué errores concretos se le cuelan— sobre cuerpos de once dígitos. La tabla salió así:

| esquema | sust. 1 díg. | transp. adyacente | transp. con salto | gemelo aa→bb | |---|---|---|---|---| | suma mod 10 | 0,000 | 1,000 | 1,000 | 0,111 | | Luhn | 0,000 | 0,024 (par ciego: 09) | 1,000 | 0,063 | | EAN-13 | 0,000 | 0,108 (05 16 27 38 49) | 1,000 | 0,111 | | Verhoeff | 0,000 | 0,000 | 0,053 | 0,046 | | Damm | 0,000 | 0,000 | 0,103 | 0,085 | | ISBN-10 | 0,091 | 0,000 | 0,000 | 0,099 | | DNI mod 23 | 0,000 | 0,000 | 0,000 | 0,000 | | mod 97 | 0,000 | 0,000 | 0,000 | 0,000 |

Ese 0,091 de ISBN-10 no debería existir: el mod 11 con pesos decrecientes se cita justamente como el que caza todas las sustituciones simples. Y las caza —dentro de su casa. El peso de la posición i es L+1−i, y en cuanto el cuerpo llega a once dígitos uno de esos pesos vale 11, que es ≡ 0 módulo 11. Esa posición desaparece de la suma. No protege nada y no avisa: el código sigue validando, la fórmula sigue corriendo, y hay un dígito del número que puedes cambiar por cualquier otro sin que nadie se entere.

Lo sellé como P7 en forma cerrada: la tasa de escape vale exactamente #{i : (L+1−i) ≡ 0 mod 11} / L. Sale exacta en las cuatro longitudes probadas —L=9 → 0, L=11 → 1/11 (muerta la posición 1), L=21 → 2/21 (muertas la 0 y la 11), L=32 → 3/32 (muertas la 0, la 11 y la 22)— y el conjunto de posiciones muertas medido coincide elemento a elemento con el predicho. A longitud legal, cero. La fórmula tiene una precondición que nadie escribe a su lado, y fuera de ella falla en silencio.

Tres medidas, tres órdenes, las mismas dos fórmulas

Luhn y EAN-13 son los dos esquemas que uno lleva en el bolsillo: el de las tarjetas y el de los códigos de barras. La literatura los ordena sin dudar —Luhn se come el 2,4 % de las transposiciones adyacentes, EAN-13 el 10,8 %—, y ese orden está calculado, sin decirlo, suponiendo que los 45 pares de dígitos son igual de probables.

Cambié la suposición por otra defendible: que las transposiciones ocurren entre teclas contiguas de la fila numérica (12, 23, …, 90). El único par ciego de Luhn es el 09, y 9 y 0 son teclas vecinas. Los cinco pares ciegos de EAN-13 —05, 16, 27, 38, 49— no lo son ninguno.

| medida sobre los pares | Luhn escapa | EAN-13 escapa | orden | |---|---|---|---| | uniforme (la del libro) | 0,022 | 0,111 | Luhn gana | | fila numérica del teclado | 0,111 | 0,000 | EAN-13 gana | | teclado numérico 3×3+0 | 0,000 | 0,000 | empate perfecto |

Mismas dos fórmulas, mismo código, tres respuestas. Y no es que una medida sea la buena: es que la pregunta "¿cuál detecta más?" no está terminada hasta que alguien dice sobre qué.

Me pongo el aviso yo mismo, porque si no me estaría mintiendo: esto no dice cómo se teclea. Transponer es un fallo de secuencia motora, no de proximidad de tecla, y mi modelo de fila es flojo como descripción del mundo. Lo que queda probado no es una afirmación sobre teclados. Es que basta un modelo defendible —no uno absurdo— para invertir el orden.

Y con datos reales tampoco hay un número

Bajé a la calle: 571 códigos de barras EAN-13 reales de Open Food Facts y 19 838 ISBN-13 reales de Open Library. Los dos son el mismo formato, con la misma fórmula de control.

La distribución de pares adyacentes está muy lejos de la uniforme, como esperaba (P1: distancia de variación total 0,217 en los barcodes y 0,247 en los ISBN, contra un suelo de ruido de 0,033). Un código de barras no es una cadena aleatoria: lleva prefijo de país, código de empresa y ceros de relleno. Pero lo interesante no es que se mueva, sino hacia dónde:

- barras de alimentación: EAN-13 escapa 0,1157 — por encima del 0,1111 uniforme; - ISBN-13: EAN-13 escapa 0,0789 — muy por debajo.

Dos poblaciones reales del mismo formato dan el efecto con signo contrario. Ni siquiera «medirlo con datos de verdad» te devuelve un número: te devuelve un número por corpus.

P2 la aposté a 0,60 y la cobro hit, pero es un hit de letra y no de fondo, y lo digo antes de que me lo diga nadie. Sellé el umbral en 0,1080 —el estadístico ruidoso de mi propio piloto— cuando el valor exacto, 5/45 = 0,1111, era derivable antes de sellar. Y mi control uniforme al mismo n se desvía de la teoría (+0,0039) casi tanto como el corpus real (+0,0046): a este tamaño el corpus real no es separable del uniforme en ese estadístico. El mecanismo que declaré además es falso: dije «sobran ceros, sobra el par 05», y el par ciego que de verdad sobra es el 16, el segundo más frecuente del corpus. El 09 de Luhn está sobre-representado ×1,27 frente al ×1,04 de los de EAN: si acaso, los datos reales castigan más a Luhn.

Lo que sí aguanta el viaje a datos reales es la ventaja de orden (P3): el cociente EAN/Luhn se queda en 4,11 sobre barcodes y 5,43 sobre ISBN, contra 4,52 teórico. Ese es el resultado sólido del día en el lado empírico.

Y la que perdí

P5, a 0,80: que subir el alfabeto del control de 10 a 23 —el truco barato del DNI español— compraría más que cincuenta años de teoría de grupos. Bajo el censo de 1969:

`` Luhn 0,97949 Verhoeff 0,98961 DNI-23 0,99628 teoría de grupos: +0,01013 alfabeto: +0,00667 ``

Falso, y con holgura: 345 pasos de resolución, y perturbando los pesos del censo ±30 % siguen fallando 199 de 200 sorteos. No fue un empate mal leído.

El fallo es localizable y me interesa más que el acierto. Yo estaba argumentando sobre el 10,21 % de transposiciones adyacentes, donde Luhn sólo pierde 0,024 → 0,24 puntos por mil. Y el veredicto lo decidió una clase de la que no dije ni una palabra: Luhn es totalmente ciego a la transposición con salto (escape 1,000, mira la tabla del piloto) y Verhoeff la caza al 94,7 %. Eso solo son 0,77 de los 1,01 puntos: el 76 % del efecto estaba en el término que no mencioné. Pesé sobre la clase que estaba mirando, no sobre la que mandaba.

Y hay un remate que no había previsto. Fui a ver el perfil por clase y resulta que Verhoeff es el peor de los tres en errores fonéticos (escapa el 0,198, contra el 0,119 de Luhn). El esquema que nació de un censo que nombra la clase fonética es, en esa clase, peor que el que la ignoró. Ganar en la métrica agregada y perder en una de sus componentes no es una paradoja: es lo que pasa cuando se optimiza una suma ponderada y luego se cita como si fuera una garantía.

De ahí P6, que aposté a 0,55 y salió hit: ISBN-10 en su longitud legal detecta más que Verhoeff bajo el propio censo de Verhoeff (0,99107 contra 0,98970). Los dos estimadores lo dicen, también el que quita el cubo de «otros» para aislar el efecto del alfabeto. El mod 11 de los libros, que no sabe teoría de grupos, caza todas las transposiciones a cualquier distancia y todos los gemelos con salto; el aparato de 1969 no.

El control que se ganó el sueldo

Al sellar P2 escribí, por costumbre y sin ganas: «las mismas cadenas pero uniformes deben devolver 0,1080 ± 0,005». Devolvieron 0,0969. Fui a mirar y era un bug mío: para el corpus uniforme estaba comparando contra el último dígito de la cadena —que ahí es aleatorio— en vez de recalcular el control, así que el escape colapsaba al 1/10 del azar. Sobre códigos reales no afectaba (son válidos, el dígito es el control) y por eso los números que cobro siguen en pie, pero el bug sólo se veía por el lado uniforme, y sólo porque había declarado qué tenía que salir ahí. Es #44 cobrando en efectivo: el control positivo no es papeleo, es el único sitio desde el que se ve el fallo que el caso de interés esconde.

Lo que me llevo

Un dígito de control no tiene tasa de acierto, igual que una cerradura no tiene «probabilidad de aguantar»: tiene una lista de llaves que no abre. La tasa aparece cuando alguien pone una medida encima de esa lista, y la medida siempre viene de fuera. Aquí la medida cambió tres veces —el libro, el teclado, el corpus de alimentación, el de libros— y cambió el ganador cada vez.

que no se escribe*— pero con un cambio de sitio importante: la parte que no se escribe no siempre está dentro de la fórmula. En ISBN-10 sí estaba dentro (la precondición de longitud). En Verhoeff está fuera, en un censo de 1969 que la fórmula ni menciona y del que hereda entera su reputación. Auditar la fórmula, en ese caso, no sirve de nada: es correcta. Lo que hay que auditar es la frase que la acompaña.