Identificación falsa > Artículos > Números de teléfono falsos que no pueden existir: un defecto del 12 % oculto en una sola llamada a `mt_rand`

Números de teléfono falsos que no pueden existir: un defecto del 12 % oculto en una sola llamada a mt_rand

Aproximadamente uno de cada ocho de los números de teléfono estadounidenses y canadienses que emitía nuestro generador no podía existir. No es que «pareciesen raros» — no podían existir, en el sentido de que el North American Numbering Plan los prohíbe y cualquier validador que se le ocurra nombrar los rechaza de un vistazo.

La primera línea del fichero cached/en_US/phone.txt desplegado era +12121007909. Código de área 212, Manhattan, absolutamente real. Después, el código de central: 100. No existe ninguna central 100 en Manhattan ni en ningún otro sitio, y nunca podrá existir.

La causa fue una sola llamada a mt_rand(1, 9).

Lo que hace que esto merezca la pena contarse no es el defecto. Es que la corrección evidente habría sido peor que el fallo, por una razón que no tiene nada que ver con los números de teléfono — y que corregirlo bien nos obligó a plantearnos una pregunta que llevábamos tiempo evitando: si generar números de teléfono plausibles es siquiera buena idea.

La regla que se incumplía

Un número norteamericano es NPA-NXX-XXXX. NPA es el código de área, NXX el código de central, XXXX la línea de abonado.

Al NXX se le aplican dos restricciones en las que casi nadie repara:

  • El primer dígito debe estar entre 2 y 9. Un 0 o un 1 inicial es estructuralmente imposible, porque 0 y 1 son los prefijos de operadora y de larga distancia. Una central que empezase por cualquiera de los dos sería inalcanzable por construcción.
  • Los códigos N11 están reservados. 211, 311, 411, 511, 611, 711, 811, 911 son códigos de servicio y nunca se asignan a abonados.

Existe una tercera convención: 555 es la central ficticia reservada, la que usa cualquier película estadounidense. El plan de numeración no la prohíbe como prohíbe 1XX, pero está apartada, y un número que pertenezca a ella resulta reconociblemente falso para cualquiera que haya visto la televisión.

Nuestro generador elegía un código de área real de una tabla y luego rellenaba los siete dígitos restantes:

$num .= (string) mt_rand(1, 9);                    // first subscriber digit: not 0
for ($i = 1; $i < $rest; $i++) $num .= (string) mt_rand(0, 9);

El comentario explica la intención: no empezar nunca por 0. La intención es correcta por la razón equivocada, y se queda un dígito corta. mt_rand(1, 9) excluye el 0 y admite el 1 — precisamente el dígito que el NANP también prohíbe. Una novena parte de todos los números norteamericanos que el sitio había producido en toda su vida nacía inválida.

Lo que en realidad medía

Medición hecha sobre los ficheros de datos desplegados, unos 20.000 números por locale, el 18 de julio de 2026:

LocaleNúmerosNXX empieza por 1Código de servicio N11555Total inválidos
en_US19.9992.233 (11,17 %)190 (0,95 %)302.423 (12,12 %)
en_CA20.0002.229 (11,14 %)184 (0,92 %)182.413 (12,06 %)
fr_CA19.9982.222 (11,11 %)178 (0,89 %)242.400 (12,00 %)

Las tres filas coinciden porque el defecto está en el algoritmo, no en los datos — todos los locales NANP comparten el mismo camino de código y, por tanto, la misma tasa de fallo. Volver a simular el algoritmo previo a la corrección sobre 200.000 números por locale lo reproduce con dos decimales de precisión: 11,02 % de 1 inicial, 0,99 % de N11, 0,11 % de 555, 12,03 % en unión.

El valor teórico zanja la cuestión. NXX se extrae de 900 combinaciones equiprobables (primer dígito de 1 a 9, los otros dos de 0 a 9):

  • 100 de ellas empiezan por 1 → 11,111 %
  • 9 de ellas son N11 → 1,000 %, pero 111 ya está contado arriba, así que solo aporta 8 nuevas
  • 555 añade 1 más

(100 + 8 + 1) / 900 = 12.111%. No es la suma de las columnas — las columnas se solapan, y sumarlas es la manera de obtener un total falso que aun así parece más o menos correcto.

Eso ya es un pequeño aviso en sí mismo. Un comentario en el código que describía este defecto citaba un 11,9 %, obtenido sumando componentes redondeadas que comparten un miembro. La cifra real es 12,1 %. Nadie lo habría detectado nunca leyéndolo, porque 11,9 % y 12,1 % son igual de plausibles. Las cifras en los comentarios son afirmaciones sin verificar disfrazadas de documentación — un punto que desarrollamos largamente en Una prueba que no puede fallar y que acto seguido demostramos sobre nosotros mismos.

Por qué la corrección evidente es la equivocada

La reparación natural es un bucle de rechazo:

do {
    $nxx = generate_nxx();
} while (!nanp_valid($nxx));

Tres líneas, una salida perfectamente uniforme sobre el espacio válido, y habría roto el sitio.

La garantía central de nuestro generador es que una URL es un enlace permanente. La ficha situada en una dirección dada se deriva combinando mediante hash la sal secreta del sitio con el id; el resultado inicializa el PRNG, tras lo cual cada campo se extrae de un único flujo determinista — nombre de pila, apellido, ciudad, calle, código postal, empleador, teléfono. El hash exacto, su truncamiento y el propio secreto no se publican aquí deliberadamente. La misma URL da la misma persona hoy, el año que viene y en un servidor reconstruido.

Esa garantía tiene una consecuencia frágil: el flujo es posicional. El campo n recibe lo que mt_rand devuelve en la posición n. Si algún campo anterior consume un número de extracciones distinto del que consumía antes, todos los campos siguientes se desplazan y la ficha cambia por completo.

Un bucle de rechazo consume un número de extracciones dependiente de los datos. La mayoría de los números pasan al primer intento; alrededor de uno de cada ocho necesita un segundo; a veces un tercero. La cuenta depende de los valores extraídos, que dependen de la semilla. Así que, para aproximadamente una ficha de cada ocho, el campo del teléfono consumiría una extracción adicional y todo lo que va después en el flujo se movería.

El resultado visible para el usuario no es «algunos números de teléfono han cambiado». Es que uno de cada ocho enlaces permanentes lleva ahora a una persona completamente distinta — otro nombre, otra ciudad, otro empleador — porque un número de teléfono situado tres campos más arriba se comió una extracción aleatoria más de las que se comía antes.

Este es el mismo invariante que protegen las funciones de selección con mt_srand($keep), y el mismo alrededor del cual se construyeron las pruebas de mutación. Que el campo del teléfono sea correcto vale mucho. No vale el enlace permanente.

La corrección: reparar los dígitos, no la extracción

La restricción queda, por tanto, fijada antes de empezar: el número de llamadas a mt_rand no debe depender de lo que devuelvan. Eso descarta el rechazo, y descarta cualquier extracción adicional condicional.

Lo que queda es reparar los dígitos que ya se tienen en la mano:

if ($cc === '1' && $rest >= 7) {
    $npa = substr($num, 0, 3);          // area code, from the prefix table
    $nxx = substr($num, 3, 3);          // central office code
    $sub = substr($num, 6);             // 4 subscriber digits

    if ($nxx[0] === '1') $nxx[0] = '2';                    // N must be 2-9
    if ($nxx[1] === '1' && $nxx[2] === '1') $nxx[2] = '0';  // not N11
    if ($nxx === '555') $nxx = '554';                       // 555 is reserved

    $num = $npa . $nxx . $sub;
}

Ninguna rama extrae. El número de extracciones es constante para cualquier entrada, de modo que el flujo aterriza en una posición idéntica tanto si el número necesitaba reparación como si no. Repetir la medición después de la corrección da un 0.00% de inválidos en los tres locales, y la comprobación de determinismo sigue devolviendo números idénticos para semillas idénticas.

El coste es honesto y conviene enunciarlo: la distribución de salida ya no es uniforme. Cada central 1XX se pliega sobre la 2XX correspondiente, de modo que los códigos 2XX aparecen aproximadamente el doble de veces que los 3XX a 9XX. Los códigos N11 se pliegan sobre N10, y 555 sobre 554. Eso sesga alrededor del 12 % de los números hacia centrales vecinas.

¿Es aceptable? Para esta aplicación, sí, y merece la pena ser preciso sobre el motivo. Nadie inspecciona la distribución de los códigos de central en un corpus de identidades falsas. Todo el mundo se fija en un número de teléfono que un formulario de alta rechaza. El sesgo es invisible; la invalidez no lo era. Si el campo hubiera alimentado un modelo estadístico en lugar de una ficha de visualización, el compromiso habría ido en sentido contrario — y habríamos tenido que resolver el problema del determinismo de otra manera, probablemente dando al campo del teléfono su propio flujo con semilla independiente, para que su número de extracciones pudiera variar sin perturbar nada aguas abajo.

Esa opción estaba disponible y no la tomamos, porque cuesta una segunda vía de siembra en cada campo que algún día pudiera necesitarla. Dejar constancia de por qué se eligió una corrección más barata es más útil que dejar constancia de la corrección.

La misma auditoría encontró dos cosas más pequeñas

Códigos de área duplicados. La lista de prefijos de fr_CA contenía once entradas, pero 367 y 438 aparecían dos veces cada uno:

'fr_CA' => ['1', ['514','438','450','579','418','367','581','819','873','367','438'], 10],

La selección es mt_rand(0, count - 1) sobre la lista en bruto, así que esos dos códigos salían al 18,18 % cada uno frente al 9,09 % de los otros siete. No se producía nada inválido; Quebec simplemente tenía dos ciudades el doble de pobladas de lo que dice el plan de numeración. La corrección es aplicar array_unique en el momento de la selección, lo que mantiene el número de extracciones en uno y no perturba nada. En el conjunto de las 65 entradas de locale, la tabla contiene 959 prefijos, de los cuales 957 son distintos — esos dos duplicados eran los únicos de toda la tabla.

Una restricción aplicada con demasiada amplitud. La regla mt_rand(1, 9) — el primer dígito de abonado nunca es 0 — se aplica a todos los locales, justificada por el comentario «de lo contrario el número parecería un número en formato nacional con un cero inicial». Ese razonamiento es erróneo. El cero inicial del formato nacional va antes del prefijo (07… en el Reino Unido, 06… en los Países Bajos), no dentro de la parte de abonado. En la mayoría de los países, ahí el 0 es un dígito perfectamente legal.

El efecto es que se descarta el 10 % del espacio de generación sin motivo, en 62 locales donde la regla no sirve de nada. En los tres locales NANP la regla resulta útil por accidente — bloquea las centrales 0XX — pero es también la razón de que el problema real siguiera oculto, porque da la impresión de que la cuestión del dígito inicial ya está resuelta. Una regla medio acertada en el único sitio donde importa es un buen disfraz para una regla equivocada en todos los demás.

Una auditoría que no encuentra nada también es un resultado

Todo lo anterior es un defecto. Eso da una impresión engañosa de lo que supone auditar una tabla de datos, así que merece la pena relatar el resultado contrario con la misma extensión.

Comprobamos Dinamarca, Suecia y Noruega frente a los documentos primarios de numeración de sus reguladores — cada prefijo, cada longitud de número, cada exclusión. El resultado fue ninguna corrección obligatoria. Los prefijos eran correctos, las longitudes eran correctas, las omisiones deliberadas eran correctas. El único cambio en todo el conjunto fueron dos prefijos daneses, 24 y 25, que ahora están presentes y elevan la lista danesa a 26 entradas.

Póngalo al lado del caso norteamericano en la misma base de código. Allí, una línea de código producía una tasa de defectos del 12 % en tres locales. Aquí, una comprobación cuidadosa frente a fuentes primarias confirmó que la tabla ya era correcta. Ambas auditorías costaron aproximadamente el mismo esfuerzo, y solo una produjo un hallazgo.

Esto importa por un sesgo que se acumula rápido: si todas las auditorías que redacta encontraron algo, empieza a creer que una auditoría que no encuentra nada se hizo mal. No se hizo mal. Un resultado limpio es información — convierte una suposición en un hecho comprobado, y ese hecho comprobado es lo que le permite dejar de reexaminar los prefijos daneses cada vez que aparece un fallo de teléfonos en otra parte. Las filas noruega y sueca de nuestra tabla se creían correctas antes. Ahora se saben correctas, y ese es un estado distinto y mejor aunque no haya cambiado ni un solo carácter.

También liquidó un mito concreto. Se repite mucho que los números de móvil suecos tienen longitud variable. No la tienen. La tabla de la PTS da, para cada uno de los prefijos 70, 72, 73, 76 y 79, un máximo igual al mínimo e igual a 9 dígitos. La confusión viene de los números geográficos suecos, que sí varían de verdad entre 7 y 9 dígitos. Nuestros datos tenían la longitud fija correcta desde siempre — pero antes de la comprobación, tener razón y repetir un rumor eran indistinguibles desde dentro.

La misma tabla, dos fiabilidades

El plan danés sacó a la luz algo que no tiene equivalente en el NANP y que cambia para qué se puede usar la tabla de prefijos.

El documento danés reserva rangos para uso móvil con la palabra fortrinsvispredominantemente, no exclusivamente: «Nummerserier, der er fortrinsvis afsat til mobilkommunikation». La consecuencia es que dentro de los rangos formalmente de red fija hay unas 90 subseries de tres dígitos emitidas para servicio móvil — 342, 344349, 431, 627, 771772 y otras. Y la portabilidad numérica danesa es total, así que el prefijo de un número real le dice de qué bloque se extrajo originalmente y absolutamente nada sobre quién lo opera hoy ni con qué tecnología.

Fíjese ahora en que esto afecta de forma completamente distinta a los dos sentidos de uso:

Sentido de usoLo que le da la tabla de prefijosFiabilidad
Generación — emitir un número de móvil danés plausibleTodo lo extraído de estos rangos es legítimamente móvilCorrecto. Los rangos son móviles por asignación; eso es todo lo que exige la generación.
Clasificación — decidir si un número real dado es móvilUna conjetura basada en el bloque de origen, desbaratada por las ~90 subseries móviles en rangos fijos y por la portabilidadSolo heurística.

La misma tabla, los mismos datos, fiabilidad opuesta según el sentido en el que se recorra. Es fácil equivocarse aquí, porque una tabla que se ha validado frente a un regulador da la sensación de estar validada para todos los usos, y no lo está. La nuestra está validada para el sentido en el que la usamos — y si alguien la coge alguna vez para responder a «¿es móvil el número de este cliente?», producirá respuestas rotundas, plausibles y a menudo erróneas.

Las reglas estructurales del NANP con las que abría este artículo no tienen esa propiedad: NXX no puede empezar por 1, y eso vale en ambos sentidos, para siempre. Es fácil generalizar a partir de una regla así y suponer que los planes de numeración son nítidos. La mayoría no lo son. Dinamarca dice predominantemente, y un adverbio en el documento de un regulador es la diferencia entre un hecho y una estimación.

La pregunta de fondo: ¿de quién es este número?

Corregir la validez estructural hace que los números estén mejor formados. No hace nada respecto a una propiedad más incómoda, que la misma auditoría cuantificó.

Generamos a partir de prefijos reales de operadores en activo — rangos móviles auténticos, elegidos deliberadamente porque están vigentes y porque, a diferencia de los códigos de red fija, no están atados a una ciudad que después habría que mantener coherente. La consecuencia es que generamos exactamente donde viven los abonados. Un número generado no es un número que se parezca a uno real. Puede sencillamente ser uno.

Con qué probabilidad depende por completo de lo grande que sea el espacio de numeración del país en relación con su población:

LocaleEspacio de generaciónLocaleEspacio de generación
is_IS1.350.000en_GB450.000.000
me_ME8.100.000ru_RU576.000.000
lv_LV9.000.000bn_BD630.000.000
hy_AM10.800.000pt_BR1.350.000.000
ka_GE10.800.000de_DE1.530.000.000
ro_MD11.700.000zh_CN2.700.000.000
sl_SI11.700.000id_ID3.060.000.000
no_NO14.400.000en_IN3.600.000.000

Islandia es el peor caso con mucha diferencia. El generador puede emitir 1.350.000 números islandeses distintos. Islandia tiene unos 390.000 habitantes y aproximadamente otras tantas suscripciones móviles activas. Algo así como uno de cada tres o cuatro números islandeses generados pertenece a una persona real. Montenegro, Moldavia, Letonia, Eslovenia, Armenia y Georgia están todos en el mismo intervalo.

Los países grandes están mejor, pero nunca limpios. El espacio de 450.000.000 de números del Reino Unido frente a unos 80.000.000 de móviles activos significa aún que alrededor del 18 % de los números británicos generados están en servicio.

Esto no es un fallo. Es la consecuencia directa e inevitable de la decisión de diseño «prefijo real más cola aleatoria», y ningún cuidado en la cola lo cambia.

Lo que los reguladores reservan realmente — y lo que no pudimos confirmar

Varios países reservan bloques precisamente para que las películas, los manuales y los datos de prueba tengan un sitio seguro al que apuntar. Fuimos a buscarlos, y el resultado honesto es una lista mucho más corta de lo que esperábamos, más una lección sobre lo que vale un «no hemos encontrado nada».

Confirmado a partir de documentos primarios de reguladores que tenemos en disco:

PaísRango reservadoTamañoFuente
FranciaRaíces 01 99 00, 02 61 91, 03 53 01, 04 65 71, 05 36 49, 06 39 986 × 10.000 = 60.000Plan de numeración de la ARCEP, anexo 2 de la décision 2018-0881
Irlanda089 011 0000089 011 0999 (móvil)1.000ComReg 15/136r4
IrlandaCódigo de área 020, abonado de 7 dígitos, enteramente «reservado para usos de ficción»10.000.000ComReg 15/136r1
Noruega680 50000680 59999, estado BLOKKERT, para producción de televisión y cine10.000Plan de numeración de Nkom
Reino Unido07700 90000007700 900999 (móvil)1.000Ofcom, Telephone numbers for use in TV and radio drama programmes, rev. 03.2019
Alemania0171 3920000…099, 0176 04069000…099, más un puñado de números Vodafone sueltos~200BNetzA, Rufnummern für Medienproduktionen, Mitteilung 148/2021
Suecia070 1740605070 174069995PTS, Telefonnummer till böcker och filmer, decisión 09.2020
Australia~30 números listados individualmente en 0491 5xx~30ACMA, Phone numbers for use in TV shows, films and creative works

La entrada noruega es la fila más instructiva de esa tabla, porque nos resulta inútil. El bloque está en el rango 68, que es de red fija. Los números de móvil noruegos son 4x y 9x, y nuestra lista de prefijos no_NO contiene dieciséis entradas, de las cuales exactamente cero empiezan por 6. Así que el generador no puede usar el bloque noruego de ficción — y, por lo mismo, tampoco puede colarse en él por accidente. La redacción de Nkom es inequívoca («Numrene i serien skal ikke brukes til ordinær bruk»), la reserva es real, y es totalmente inaplicable al campo que estamos generando.

Eso merece enunciarse como principio general, porque «¿reserva el país X números ficticios?» es la pregunta equivocada. La correcta es «¿reserva el país X números ficticios en el rango a partir del cual genero?». Un bloque de red fija reservado no sirve de nada a un generador de móviles, y un bloque de móvil reservado no sirve de nada a quien genera fijos. La mitad del valor de la tabla anterior está en los desajustes.

Otras dos entradas fueron una sorpresa. Francia reserva seis raíces, una por zona geográfica más la de móvil — esperábamos las dos que se citan en las entradas de blog. Y Irlanda, un país de cinco millones de habitantes, ha apartado un código de área entero de diez millones de números para la ficción, junto a su pequeño bloque móvil. El bloque móvil se cita en todas partes; la asignación 020 no se cita en ninguna.

No se pudo confirmar con ninguna fuente que tengamos:

Afirmación que no podíamos sostenerEstado
Reino Unido: 01632 960xxx como segundo rango de ficciónCero apariciones en documento alguno de un regulador. Muy repetido en internet; la página de Ofcom que sí tenemos cubre únicamente el bloque móvil 07700 900.
Corea del Sur: 010-3348-xxxx y 010-6687-xxxx como centrales reservadasUn mito, y el de mayores consecuencias de esta lista — véase más abajo.
Países Bajos, Brasil, India, Islandia, Finlandia, Letonia: «sin rango reservado»No tenemos hallazgo en ningún sentido. Esto es ausencia de pruebas.
Dinamarca: «sin rango reservado»Comprobado frente al plan de numeración y no está allí. Eso es más débil de lo que parece: una reserva hecha por una decisión regulatoria aparte, fuera del plan, sería invisible para esta búsqueda. Consígnelo como «no está en el plan de numeración», no como «ausencia demostrada».

Y una afirmación que tuvimos que degradar tras comprobarla como es debido. Habíamos consignado Japón y Sudáfrica como confirmaciones firmes de «sin rango reservado». Solo una sobrevive.

En el caso de Japón, tenemos las tablas de asignación de bloques del Ministerio de Asuntos Internos y Comunicaciones (a 1 de septiembre de 2024) para los rangos 060, 070, 080 y 090. Cada bloque de cinco dígitos de 09010 a 09099 está asignado a un operador con nombre — NTT docomo, KDDI, SoftBank, Okinawa Cellular — sin ningún bloque marcado como de ficción, de pruebas, ficticio o mantenido en reserva. Eso sí es un negativo genuinamente fuerte: las tablas son exhaustivas por construcción, de modo que una categoría no listada tendría que verse como un hueco, y no hay ninguno.

En el caso de Sudáfrica, nuestra fuente de la ICASA es un PDF del Government Gazette que se extrajo como binario en gran parte ilegible. Contiene cero apariciones de «reserved», «drama», «film» o «test» — y ese cero no significa absolutamente nada, porque un fichero corrupto devuelve cero coincidencias para cualquier cadena, incluidas las que contiene con toda seguridad. Habíamos basado una conclusión en una búsqueda que no podía tener éxito.

Ese modo de fallo ya nos ha mordido antes, en una parte completamente distinta del sistema, y es objeto de un artículo propio: La comprobación que se queda ciega justo donde hace falta. La versión corta es que una búsqueda que devuelve «no se ha encontrado nada» está informando de una de dos cosas muy distintas — la cadena no está, o la búsqueda era incapaz — y la salida tiene el mismo aspecto en ambos casos.

El bloque coreano que no existe

Una «reserva» muy repetida resultó ser peor que inútil, y es la ilustración más fuerte de todo este artículo de por qué el rango importa más que la reserva.

El artículo Fictitious telephone number de Wikipedia presenta 010-3348-xxxx y 010-6687-xxxx como los números de ficción de Corea del Sur. La fuente primaria dice otra cosa. El Korean Film Council (KOFIC) tiene seis líneas en total — cuatro fijas, dos móviles — para producción cinematográfica, y publica deliberadamente solo el código de área y la central (국번), y no los números completos, precisamente para que no se usen de cualquier manera. Así que lo que existe son dos líneas de abonado concretas, no un bloque de diez mil.

Generar una cola aleatoria de cuatro dígitos dentro de la central 3348 no evitaría, por tanto, a los abonados reales. Apuntaría hacia ellos: concentraría todas las fichas coreanas en una central en la que 9.998 de los 10.000 números pertenecen a personas reales. Una «corrección» construida sobre esa cita empeora estrictamente el problema que dice resolver, y encima parece responsable mientras lo hace.

La regla general que esto enseña es más estrecha que «compruebe sus fuentes»: una reserva citada como un rango, cuando el documento primario reserva números individuales, no es un rango. Ambas cosas se escriben casi igual en las fuentes secundarias.

Así que la tabla anterior tiene tres niveles, y los niveles importan más que las filas: confirmado con un documento que podemos citar, creído pero no documentado, y no investigado. Solo el primer nivel es seguro para construir encima.

El dilema, y los tres locales donde tiene respuesta

Supongamos que pasamos a los rangos reservados allí donde existan. Vea lo que eso implica.

La reserva alemana son unos 200 números. El locale alemán genera fichas sin límite. Mucho antes de haber mirado unos pocos miles de identidades alemanas, los números de teléfono empezarían a repetirse — y a repetirse de una forma inmediatamente visible, porque todos comparten un puñado de prefijos. El campo pasaría de «plausible, ocasionalmente real» a «obviamente sintético, y solo doscientas posibilidades». El bloque sueco son 95 números; el de Australia es una lista de unos treinta nombrados uno a uno, con el resto de la central circundante en servicio.

Así que no basta con que la reserva sea real. Tres condiciones tienen que cumplirse a la vez: el rango reservado debe estar en la banda móvil a partir de la cual generamos, debe ser lo bastante grande para que un conjunto de fichas no se repita visiblemente, y no debe ser un marcador cultural — el 555-01xx estadounidense es seguro, y cualquier lector estadounidense lo reconoce al instante como «un número de película», lo que cambia un tipo de falsedad por otro.

Exactamente tres locales cumplen las tres condiciones: en_GB (el 07700 900xxx de Ofcom), en_IE (el 089 011 0xxx de ComReg) y fr_FR (la raíz 06 39 98 de la ARCEP). Para esos tres, la probabilidad de que un número generado pertenezca a una persona viva es ahora cero, y no «menor» — y para Francia es la mayor ganancia individual disponible en todo el conjunto, porque alrededor del 40 % de los números franceses eran de alguien antes del cambio, frente al 18 % del Reino Unido.

El coste es visible y merece enunciarse. La reserva utilizable es de 900 números para el Reino Unido e Irlanda y de 9.000 para Francia — el subbloque que termina en …000…099 es inalcanzable porque el primer dígito de abonado siempre está entre 1 y 9. En un conjunto de 200 fichas británicas, se repiten aproximadamente 26 números de teléfono. Ese es el precio de la garantía, y se paga precisamente en los países cuyos reguladores se molestaron en ayudar, lo que sigue siendo un resultado perverso incluso cuando uno lo acepta.

Y resuelve 3 locales de 65. Los otros 62 quedan igual, incluidos todos los casos que la primera mitad de este artículo calificaba de urgentes:

  • Islandia — el peor caso de toda la tabla — no tiene arreglo. No hay ningún rango reservado en el plan islandés, y la única vía teórica (generar a partir de bloques nunca emitidos a ningún operador) necesita datos de asignación que nadie publica para Islandia.
  • Corea del Sur y Japón tampoco tienen arreglo, por las dos razones distintas de más arriba: Corea reserva líneas individuales en lugar de un bloque, y las tablas de asignación japonesas no dejan ninguna categoría sin asignar que se pueda usar.
  • Montenegro, Moldavia, Letonia, Eslovenia, Armenia y Georgia están en el mismo orden de riesgo que Islandia y tienen la misma no-respuesta.

Esa es la forma honesta del resultado: no «resuelto», sino se ha encontrado la frontera de lo resoluble y se ha hecho todo lo que queda dentro de ella. Las opciones restantes siguen siendo los mismos compromisos, y siguen abiertas:

  • Rangos reservados en todas partes donde exista uno — rechazado: dejaría a Alemania en 200 números, a Suecia en 95, a Australia en 30, y metería 555-01xx en los tres locales más leídos.
  • Rangos en servicio en todas partes, como hasta ahora — variedad máxima, y un abonado islandés real detrás de una amplia minoría de las fichas islandesas.
  • Centrales estructuralmente válidas pero deliberadamente sin asignar — códigos de central que existen en el plan pero no están asignados a ningún operador. Esto exige datos de asignación país por país de los que no disponemos, y las asignaciones cambian.

El resto del trabajo era la parte inequívoca: hacer que los números sean estructuralmente válidos, eliminar los prefijos duplicados y anotar las cifras de colisión para que el compromiso sea una decisión que alguien pueda tomar en lugar de una propiedad que nadie ha medido.

La lista de comprobación

  1. Conozca las reglas estructurales de aquello que está falsificando. «Parece un número de teléfono» no es una especificación. El NANP impone tres restricciones sobre un solo campo; nosotros implementamos la mitad de una.
  2. Cuando la salida debe ser determinista, el número de extracciones aleatorias no debe depender de los valores extraídos. Esto descarta el muestreo por rechazo, los bucles de reintento y cualquier extracción adicional condicional — y no resulta evidente hasta que muerde.
  3. Prefiera reparar los valores extraídos a volver a extraerlos. La reparación tiene coste constante. El precio es un sesgo de distribución, que suele ser lo más barato de perder.
  4. Anote lo que cuesta la corrección. «Alrededor del 12 % de los números se desplaza a una central vecina» es un hecho que la siguiente persona necesita. Una corrección silenciosa la deja redescubrir el sesgo y tratarlo como un fallo nuevo.
  5. No sume porcentajes redondeados que se solapan. Los nuestros sumaban 11,9 % donde la unión vale 12,1 %. Calcule la unión directamente o enuncie las componentes por separado.
  6. Compruebe si sus tablas de consulta tienen duplicados. Dos entradas repetidas de 959 daban a dos códigos de área canadienses el doble de peso que a sus vecinos, y nada en la salida tenía mal aspecto.
  7. Desconfíe de una justificación que es correcta por la razón equivocada. «No empezar nunca por 0» era correcto por accidente en tres locales, erróneo en sesenta y dos, y camufló el defecto real durante toda la vida del campo.
  8. Separe «confirmamos que no hay ninguno» de «no encontramos ninguno». Se leen igual en un resumen y valen cantidades completamente distintas.
  9. Una búsqueda con cero resultados sobre un fichero ilegible no es una prueba. Verifique que la búsqueda podría haber tenido éxito — busque en el fichero corrupto una cadena que sepa que está dentro antes de creerse un negativo.
  10. Pregúntese si un rango reservado está reservado en su rango. Noruega reserva un bloque de ficción que nuestro generador de móviles ni puede usar ni puede alcanzar por accidente. La existencia de una reserva no es su aplicabilidad.
  11. Lea los adverbios del regulador. Dinamarca asigna rangos «predominantemente» al móvil. Esa sola palabra significa que la tabla es sólida para generar números y no lo es para clasificarlos.
  12. Consigne las auditorías limpias como hallazgos. «Comprobado, nada incorrecto» convierte una suposición en un hecho y evita que la siguiente persona lo vuelva a comprobar. Una auditoría no se juzga por si encontró algo.
  13. Compruebe si un «rango reservado» es siquiera un rango. Corea reserva seis líneas individuales y publica solo su central. Citado de segunda mano, se lee como un bloque de diez mil, y construir sobre esa lectura habría dirigido todas las fichas coreanas hacia abonados reales.
  14. Mida las repeticiones que compra una reserva pequeña antes de aceptarla. 900 números utilizables significan unas 26 repeticiones en 200 fichas. Es una cifra que hay que aceptar deliberadamente, no descubrir en una captura de pantalla.

El defecto en sí costó una línea causarlo y ocho líneas corregirlo. Todo lo caro que tenía estaba aguas abajo: la corrección que no se podía usar, el invariante que la hacía inutilizable, y la pregunta — todavía abierta — de si un número de teléfono que podría hacer sonar el móvil de una persona real en Reikiavik tiene siquiera sitio en una página de gente inventada.

Sobre la vía de siembra y el invariante de flujo con los que este artículo choca una y otra vez, véase Cómo funciona nuestro generador. Sobre el conjunto de pruebas propio de ese invariante y cómo establecimos que era capaz de fallar, véase Una prueba que no puede fallar. Sobre otros defectos que encontramos contando en vez de mirando, véase Lo que hicimos mal.


Datos actualizados a 2026-07-18

Las mediciones del defecto se tomaron el 18 de julio de 2026, sobre share/name_gen/ng_phone.php tal como se entrega en source_share_1.1.7 y sobre los ficheros cached/<locale>/phone.txt desplegados. La investigación sobre los reguladores, el cambio a rangos reservados para en_GB, en_IE y fr_FR, y las cifras de repetición se hicieron el 21 de julio de 2026 sobre share 1.1.8.

⚠ Los rangos reservados son un cambio en los datos de numeración; los conjuntos de datos cached/<locale>/phone.txt desplegados se reconstruyen de forma centralizada, así que los tres locales llevan los números antiguos de rangos en servicio hasta que se ejecute esa reconstrucción.

Fuentes y notas:

  • Las tasas de defecto — medidas sobre datos desplegados, ~20.000 números por locale: en_US 2.423 inválidos de 19.999 (12,12 %), en_CA 2.413 de 20.000 (12,06 %), fr_CA 2.400 de 19.998 (12,00 %). Reproducidas de forma independiente volviendo a simular el algoritmo previo a la corrección sobre 200.000 números por locale, lo que da un 12,03 % de unión en los tres casos. El valor teórico es (100 + 8 + 1) / 900 = 12.111%.
  • ⚠ Una cifra de la fuente es errónea. El comentario explicativo de ng_phone.php da la tasa combinada como 11,9 %, obtenida sumando 11.00% + 0.90% + 0.11%. Esas componentes se solapan — 111 cumple a la vez la condición del 1 inicial y la condición N11 — así que no se pueden sumar, y la suma ni siquiera alcanza el total que ella misma declara (da 12,01 %). La unión correcta es 12,1 %. Este artículo usa las cifras medidas y teóricas; el comentario no se ha corregido.
  • La correcciónng_phone.php, líneas 173–183. La medición posterior a la corrección devuelve un 0,00 % de inválidos para los tres locales NANP, y mt_srand(7) ejecutado dos veces seguidas devuelve el mismo número +17375163779, lo que confirma que el número de extracciones no cambió.
  • La tabla de prefijos — 65 entradas de locale. Cuando se encontró el defecto de los duplicados, la tabla contenía 959 prefijos tal como estaban escritos y 957 distintos: 367 y 438 aparecían dos veces cada uno en una lista fr_CA de 11 entradas, lo que daba una probabilidad de selección del 18,18 % frente al 9,09 % de los otros siete códigos. Recontada el 22 de julio de 2026, la tabla contiene 963 prefijos, 963 de ellos distintos — las repeticiones de fr_CA han desaparecido de la tabla literal, y la deduplicación se sigue aplicando en el momento de la selección mediante array_values(array_unique(...)), como medida de doble seguridad.
  • La regla del dígito inicialmt_rand(1, 9) para el primer dígito de abonado se aplica a las 65 entradas. Su justificación declarada tiene que ver con el cero inicial del formato nacional, que va antes del prefijo y no dentro de la parte de abonado, de modo que la regla descarta sin motivo el 10 % del espacio de generación en los 62 locales no NANP.
  • Las cifras del espacio de generación — calculadas a partir de ng_phone_spec() como el número de números nacionales distintos que se pueden emitir por locale. Islandia: 1.350.000 frente a una población de ~390.000. Reino Unido: 450.000.000 frente a ~80.000.000 de suscripciones móviles activas, de donde sale la estimación del ~18 % de números en servicio. Son estimaciones de orden de magnitud frente a totales de suscripciones, no una comprobación contra ninguna base de datos de asignaciones.
  • Francia — seis raíces de ficción 01 99 00 / 02 61 91 / 03 53 01 / 04 65 71 / 05 36 49 / 06 39 98, de una copia extraída del plan nacional de numeración de la ARCEP, en la tabla titulada Racines (format national). El plan cita el anexo 2 de la décision n° 2018-0881 modifiée, que regula la gestión del plan de numeración en general y no el bloque de ficción en concreto. El total de 60.000 es deducido (6 × 10.000), no está enunciado en el documento.
  • Irlanda089 011 0000 to 089 011 0999 is reserved for drama use, de una copia extraída de ComReg 15/136r4. Aparte, ComReg 15/136r1 recoge el código de área 020 con números de abonado de 7 dígitos como Reserved for Drama purposes; el total implícito de 10.000.000 es nuestro, no de ComReg.
  • Reino Unido — el bloque 07700 900000-900999 está consignado en nuestra propia nota de auditoría como información ya conocida. No tenemos ningún documento de Ofcom. Una tirada de 500.000 números británicos generados produjo 0 aciertos en ese bloque, coherente con la tasa esperada de aproximadamente 1 de cada 450.000. El rango 01632 960xxx, tan citado, no aparece en ninguna fuente que tengamos.
  • La auditoría nórdica — Dinamarca, Suecia y Noruega comprobadas frente a los documentos primarios de numeración de sus reguladores. Ninguna corrección obligatoria. El único cambio fue añadir los prefijos daneses 24 y 25; la lista da_DK que se entrega contiene ahora 26 prefijos, todos de dos dígitos, longitud nacional 8, lo que da un espacio de generación de 23.400.000. Verificado directamente en ng_phone_spec() en la fecha indicada arriba.
  • La longitud de los números suecossv_SE entrega 70, 72, 73, 76, 79 con una longitud nacional fija de 9, espacio de generación 45.000.000. La tabla de la PTS da máximo = mínimo = 9 para los cinco prefijos, así que la afirmación tan repetida de que los números de móvil suecos varían de longitud es falsa; la variación pertenece a los números geográficos suecos, que van de 7 a 9 dígitos. Nuestros datos no necesitaron ningún cambio.
  • El rango bloqueado de Noruega680 50000680 59999, estado BLOKKERT, reservado por Nkom para producción de televisión y cine, con la nota «Numrene i serien skal ikke brukes til ordinær bruk». Confirmado inutilizable y sin posibilidad de colisión mediante inspección de la tabla entregada: no_NO contiene 16 prefijos (40 41 45 46 47 48 90 91 92 93 94 95 96 97 98 99), de los cuales cero empiezan por 6.
  • La formulación danesa de «predominantemente móvil» — el plan dice «Nummerserier, der er fortrinsvis afsat til mobilkommunikation». Alrededor de 90 subseries de tres dígitos situadas dentro de rangos formalmente fijos se emiten para uso móvil (342, 344349, 431, 627, 771772 entre ellas), y la portabilidad es total. El recuento de ~90 procede de la auditoría y no se ha vuelto a contar aquí de forma independiente. La asimetría entre generación y clasificación se deriva de la redacción y de la portabilidad, no de una medición.
  • Alemania y Suecia — las cifras 5.210 (Bundesnetzagentur, Verfügung 148/2021) y 495 (PTS) no se pudieron sustentar. No tenemos ningún documento de la BNetzA. El plan de numeración de la PTS de 8 de enero de 2024 sí lo tenemos, pero se extrajo con contenido en parte binario y sin ninguna sección recuperable sobre rangos reservados; la auditoría nórdica posterior tampoco encontró ninguna reserva de ficción en el plan sueco, lo que es coherente con que la cifra de 495 sea errónea, pero no refuta una reserva hecha fuera del plan. Ambas se reportan aquí como no verificadas.
  • Japón — tablas de asignación de bloques 電気通信番号指定状況 del MIC, a 1 de septiembre de 2024, para los rangos 060/070/080/090. Todos los bloques 0901009099 están asignados a operadores con nombre, sin ninguna categoría de ficción, prueba, ficticio o reserva. Tratado como un negativo fuerte porque las tablas son exhaustivas.
  • Sudáfrica — el extracto del Government Gazette de la ICASA está en gran parte ilegible y arroja cero coincidencias para «reserved», «drama», «film» y «test». Esto no es prueba de ausencia, y cualquier constancia previa de ello como negativo confirmado era errónea.
  • Países Bajos, Brasil, India, Islandia, Finlandia, Letonia — ningún hallazgo en ningún sentido. Listados como no investigados y no como países sin rango reservado.

← Artículos