¿Cómo puedo crear un número aleatorio de 16 dígitos que no existe previamente en una lista?
Digamos que tengo la siguiente lista:
const nums = [7856328870763265, 0107654389657487];
Necesito una función para generar números aleatorios de 16 dígitos pero eso no crea duplicados.
tengo lo siguiente:
const val = Math.floor(1000 + Math.random() * 9000).toString(); const random16digitnumber = +val+val+val+val; console.log(random16digitnumber); console.log(typeof random16digitnumber);
Pero me temo que en algún momento comenzará a crear duplicados. Estoy usando el número aleatorio de 16 dígitos como clave principal en una base de datos SQL para un pequeño proyecto escolar.
Entonces, volviendo a mi ejemplo, ¿cómo puedo crear un número aleatorio de 16 dígitos que no exista previamente en una matriz?
No sé mucho sobre JavaScript, pero les daré una solución general.
Debe usar una declaración de bucle para recorrer la lista y verificar si el número generado está en la matriz. Si no está en la matriz, agréguelo/empújelo a la lista. De lo contrario, regenere el número aleatorio.
Podría haberlo escrito en php o python
Responderé con un comentario en línea. Dejé tu algo "como está". Puede haber razones por las que lo estás haciendo de esta manera; así que simplemente implementé la lógica que deseabas.
const nums = [7856328870763265, 0107654389657487]; const getNextRandomNumber = () => { const val = Math.floor(1000 + Math.random() * 9000).toString(); const candidate = +val+val+val+val; // the generated number is part of the list; // recursively call this function to generate another one // (this works like a loop, just using call recursion) // until a number is found that is not part of the list // then the return below this if() is triggered // and the "good" candidate is returned if (nums[candidate]) { return getNextRandomNumber(); } // parseInt makes sure the string is converted back to number // making sure we're using base 10, even if the first digit // might be 0 return parseInt(candidate, 10); } // push() adds an element to the array // the return value (100% guaranteed to be collision free random number) // is added via the function call. The function logic makes sure // it is absolutely unique nums.push(getNextRandomNumber());
Si desea una verdadera aleatoriedad sin duplicados, deberá verificar la lista cada vez para asegurarse de que no se haya incluido. Eventualmente, eso podría convertirse en un lastre para el sistema, pero no hay alternativa.
Si desea una posibilidad lo suficientemente pequeña de que aparezcan duplicados para que su código pueda ignorarlo (a menos que tenga un volumen fenomenal), entonces los GUID son probablemente su mejor opción... pero estos tienen más de 16 dígitos.
Sin embargo, si desea que los números que aparecen a simple vista sean aleatorios, aunque están lejos de serlo, entonces un algoritmo simple le dará los 10^16
números en un orden aleatorio. Podemos lograr esto tomando números posteriores como una transformación lineal de los actuales. Podemos multiplicar nuestro valor actual por algún número, a
y agregar otro valor, b
, luego tomar los últimos 16 dígitos para obtener el siguiente valor. Siempre que a
y b
no tengan factores propios comunes y tampoco tengan factores propios comunes con 10^16, este proceso recorrerá todos los números desde cero hasta 9999999999999999
en un orden aparentemente aleatorio.
La forma más fácil de asegurarse de que no haya factores comunes es simplemente elegir dos números primos de 16 dígitos, lo que podemos hacer en un sitio como https://bigprimes.org/ .
Si podemos mantener o buscar fácilmente la última identificación utilizada, entonces podemos escribirla así:
const a = BigInt ( '7791448648907857') const b = BigInt ( '2320712743817497') const c = BigInt ('10000000000000000') const nextId = (previousId) => ((a * BigInt(previousId) + b) % c) .toString () .padStart ('0', 16) const lastRecord = {id: '1234567890123456', more: 'fields'} console .log (nextId (lastRecord .id))
Si no podemos rastrear fácilmente la última identificación, pero podemos mantener un contador secuencial, digamos n
, siempre podemos generarlo usando la fórmula
id_n = (a ** n + b * ((a ** n - 1) / (a - 1))) % c
Eso implicaría administrar de manera eficiente la exponenciación modular , pero ese es un problema bien resuelto y es bastante fácil de implementar.
No olvide que esto no solo no es criptográficamente seguro, sino que está lejos de ser aleatorio. Pero le dará un número de aspecto aleatorio sin repeticiones.