El JavaScript Matemáticas.random() función devuelve un valor aleatorio entre 0 y 1, automáticamente cabeza de serie basado en la hora actual (similar a Java, creo). Sin embargo, no creo que haya alguna manera de que te semillas propias para ello.

¿Cómo puedo hacer un generador de números aleatorios que puedo ofrecer mi propio valor de la semilla, por lo que puedo tener de producir una secuencia predecible de (pseudo)aleatorios los números?

  • Nota: En aras de mantener esta pregunta breve y focalizado, he dividido el código que estaba en la pregunta anterior fuera a un Wiki de la Comunidad de respuesta a continuación.
InformationsquelleAutor scunliffe | 2009-01-08

9 Comentarios

  1. 111

    Una opción es http://davidbau.com/seedrandom que es un seedable basado en RC4 de Matemáticas.aleatorio() reemplazo con propiedades atractivas.

    • David Bau del seedrandom se ha convertido en popular suficiente como para que él la mantiene aquí en github. Es una pena ECMAScript ha sido tan atrás escena durante tanto tiempo, que cosas como esta no están incluidos en el idioma. En serio, no siembra!!!
    • Es la vergüenza y la gloria de JS que esto es necesario y posible. Es bastante fresco que se puede incluir un archivo y obtener compatible cambios realizados en el objeto de Matemáticas. No está mal para 10 días de trabajo, Brendan Eich.
  2. 23

    si usted no necesita la siembra de capacidad, sólo tiene que utilizar Math.random() y construir funciones de auxiliar a su alrededor (por ejemplo. randRange(start, end)).

    No estoy seguro de lo del generador de números aleatorios que se está utilizando, pero es mejor conocer y documentar para que estés consciente de sus características y limitaciones.

    Como Starkii dijo, Mersenne Twister es un buen PRNG, pero no es fácil de implementar. Si desea hacerlo usted mismo tratar de implementar un LCG – es muy fácil, ha decente aleatoriedad cualidades (no tan buena como la de Mersenne Twister), y usted puede utilizar algunas de las más populares constantes.

    JS:

    function RNG(seed) {
    //LCG using GCC's constants
    this.m = 0x80000000; //2**31;
    this.a = 1103515245;
    this.c = 12345;
    this.state = seed ? seed : Math.floor(Math.random() * (this.m - 1));
    }
    RNG.prototype.nextInt = function() {
    this.state = (this.a * this.state + this.c) % this.m;
    return this.state;
    }
    RNG.prototype.nextFloat = function() {
    //returns in range [0,1]
    return this.nextInt() / (this.m - 1);
    }
    RNG.prototype.nextRange = function(start, end) {
    //returns in range [start, end): including start, excluding end
    //can't modulu nextInt because of weak randomness in lower bits
    var rangeSize = end - start;
    var randomUnder1 = this.nextInt() / this.m;
    return start + Math.floor(randomUnder1 * rangeSize);
    }
    RNG.prototype.choice = function(array) {
    return array[this.nextRange(0, array.length)];
    }
    var rng = new RNG(20);
    for (var i = 0; i < 10; i++)
    console.log(rng.nextRange(10, 50));
    var digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
    for (var i = 0; i < 10; i++)
    console.log(rng.choice(digits));

    • No debería el módulo de ser 2^31? He leído este algoritmo de wiki.
    • buena captura! Fijo.
    • Gracias, este es lo suficientemente bueno para mis propósitos.
    • Sólo por lo que son conscientes, esto no es «correcto» en el sentido de que no sale lo de las matemáticas dicta. En otras palabras, un lenguaje que se puedan manejar grandes números tendrá un resultado diferente. JS ahoga en los grandes números y las chuletas de precisión (son carrozas, después de todo).
    • -1 Este LCG implementación de bustos el límite exacto de los números enteros en JavaScript como this.a * this.state es probable que resulte en un número mayor que 2^53. El resultado es un limitado rango de salida, y para algunas semillas posiblemente un período muy corto. Más en general, el uso de una potencia de dos, por m resultar en algo bastante obvio patrones, cuando usted está consumiendo un módulo de operación en lugar de una simple truncamiento de todos modos no hay ninguna razón para no usar un primo.
  3. 22

    Si quieres ser capaz de especificar la semilla, sólo tienes que sustituir las llamadas a getSeconds() y getMinutes(). Usted podría pasar en un int y el uso de la mitad de la mod de los 60 por el valor de los segundos y la otra mitad modulo de 60 a dar a la otra parte.

    Que se dice, este método se parece a la basura. Haciendo la correcta generación de números aleatorios es muy duro. El problema obvio de esto es que la semilla de aleatorización se basa en los segundos y los minutos. Adivinar la semilla y volver a crear la secuencia de números aleatorios sólo se requiere tratando de 3600 segundo y minuto combinaciones. También significa que no son sólo 3600 distintos tipos de semillas. Esto es corregible, pero me gustaría ser sospechoso de este RNG desde el principio.

    Si quieres un mejor uso de la RNG, pruebe el Mersenne Twister. Se trata de un bien probado y bastante robusto generador de números aleatorios con una enorme órbita y excelente rendimiento.

    EDIT: yo a la verdad debe ser la correcta y se refieren a esto como un Pseudo Random Number Generator o PRNG.

    «Cualquier persona que utiliza aritmética de métodos para generar números aleatorios se encuentra en un estado de pecado.»

                                                                                                                                                              — John von Neumann

    • Con respecto a Mersenne Twister – es un gran PRNG, pero no es seguro. Tener sólo 3600 posibles estados iniciales es terrible, pero nunca debe depender de Mersenne Twister para asegurar la aleatoriedad bien.
    • Un enlace a JS las implementaciones de Mersenne Twister: matemáticas.sci.hiroshima-u.ac.jp/~m-mat/MT/VERSIONES/JAVASCRIPT/…
    • ¿Tienes una fuente para la 3600 estados iniciales? Mersenne Twister es cabeza de serie por un número de 32 bits, por lo que el PRNG debe tener 4 mil millones de dólares iniciales a los estados – sólo si la inicial de la semilla es verdaderamente aleatorio.
    • Me estaba refiriendo a la sugerencia de la semilla con una combinación de getSeconds() y getMinutes(), 60 * 60 == 3600 posibles estados iniciales. Yo no se estaba refiriendo a Mersenne Twister.
    • Ok, no estaba claro. Estaba tomando acerca de Mersenne Twister y en la siguiente frase acerca de la inicial de los estados 😉
    • Nota: La «basura» en el código que esta respuesta se refiere a, que se utiliza para ser incluidos en la pregunta, ahora se encuentra aquí.
    • Ah, Von Neumann, Ciencias de la computación y la Hombre Pequeño Ordenador. Aquellos eran los días 🙂
    • La pregunta que pide no hacer ninguna mención de que necesitan «apropiada» para la generación de números aleatorios para cualquier tipo de criptográficamente sensibles de la aplicación. Mientras que todos los de la respuesta es verdadera, sólo el primer párrafo es realmente relevante para la pregunta. Quizás añadir un fragmento de código de la propuesta de solución.

  4. 8

    El código que aparece tipo de parece un Lehmer RNG. Si este es el caso, entonces 2147483647 es el mayor signo de 32 bits entero, 2147483647 es el más grande de 32 bits prime, y 48271 es un período completo multiplicador que se utiliza para generar los números.

    Si esto es cierto, podría modificar RandomNumberGenerator a tomar en un parámetro adicional seed, y, a continuación, establezca this.seed a seed; pero usted tendrá que tener cuidado para asegurarse de que la semilla se traducirá en una buena distribución de números aleatorios (Lehmer puede ser extraño parecido), pero la mayoría de las semillas va a estar bien.

  5. 7

    El siguiente es un PRNG que pueden ser alimentados con una costumbre de la semilla. Llamar SeedRandom devolverá un generador aleatorio de la función. SeedRandom puede ser llamado sin argumentos para semilla regresado a la función random, con el tiempo actual, o puede ser llamado con 1 o 2 no negativo inters como argumentos en orden a la semilla que con los números enteros. Debido a flotar precisión del punto de siembra con valor sólo 1 sólo permite que el generador se inició a uno de los 2^53 estados diferentes.

    La devuelve al azar del generador de función de 1 argumento entero llamado limit, el límite debe estar en el rango de 1 a 4294965886, la función devolverá un número en el rango de 0 a limitar-1.

    function SeedRandom(state1,state2){
    var mod1=4294967087
    var mul1=65539
    var mod2=4294965887
    var mul2=65537
    if(typeof state1!="number"){
    state1=+new Date()
    }
    if(typeof state2!="number"){
    state2=state1
    }
    state1=state1%(mod1-1)+1
    state2=state2%(mod2-1)+1
    function random(limit){
    state1=(state1*mul1)%mod1
    state2=(state2*mul2)%mod2
    if(state1<limit && state2<limit && state1<mod1%limit && state2<mod2%limit){
    return random(limit)
    }
    return (state1+state2)%limit
    }
    return random
    }

    Ejemplo de uso:

    var generator1=SeedRandom() //Seed with current time
    var randomVariable=generator1(7) //Generate one of the numbers [0,1,2,3,4,5,6]
    var generator2=SeedRandom(42) //Seed with a specific seed
    var fixedVariable=generator2(7) //First value of this generator will always be
    //1 because of the specific seed.

    Este generador, presentan las siguientes propiedades:

    • Tiene aproximadamente 2^64 posibles diferentes estados internos.
    • Tiene un período de aproximadamente 2^63, mucho más de lo que nadie nunca necesita prácticamente en un programa JavaScript.
    • Debido a la mod de los valores de los números primos no hay ningún patrón simple en la salida, no importa el límite elegido. Esto es a diferencia de algunos de los más simples PRNGs que presentan algunos de ellos bastante de los patrones sistemáticos.
    • Descarta algunos de los resultados con el fin de conseguir una perfecta distribución no importa el límite.
    • Es relativamente lento, corre alrededor de 10 000 000 de veces por segundo en mi máquina.
    • ¿Por qué producir un patrón? for (var i = 0; i < 400; i++) { console.log("input: (" + i * 245 + ", " + i * 553 + ") | output: " + SeedRandom(i * 245, i * 553)(20)); }
    • Porque estás usando mal. No soy experto, pero esto ocurre porque están inicializando el generador en cada iteración, sólo con ver su primer valor basado en la semilla, y NO la iteración en el generador de los números subsiguientes. Creo que esto va a suceder en cualquier PRNG que no hash de la semilla en todo el intervalo especificado.
  6. 4

    Si usted programa en el Manuscrito, me he adaptado el Mersenne Twister aplicación que se trajo Christoph Henkelmann respuesta a este hilo como un manuscrito de la clase:

    /**
    * copied almost directly from Mersenne Twister implementation found in https://gist.github.com/banksean/300494
    * all rights reserved to him.
    */
    export class Random {
    static N = 624;
    static M = 397;
    static MATRIX_A = 0x9908b0df;
    /* constant vector a */
    static UPPER_MASK = 0x80000000;
    /* most significant w-r bits */
    static LOWER_MASK = 0x7fffffff;
    /* least significant r bits */
    mt = new Array(Random.N);
    /* the array for the state vector */
    mti = Random.N + 1;
    /* mti==N+1 means mt[N] is not initialized */
    constructor(seed:number = null) {
    if (seed == null) {
    seed = new Date().getTime();
    }
    this.init_genrand(seed);
    }
    private init_genrand(s:number) {
    this.mt[0] = s >>> 0;
    for (this.mti = 1; this.mti < Random.N; this.mti++) {
    var s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30);
    this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253)
    + this.mti;
    /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
    /* In the previous versions, MSBs of the seed affect   */
    /* only MSBs of the array mt[].                        */
    /* 2002/01/09 modified by Makoto Matsumoto             */
    this.mt[this.mti] >>>= 0;
    /* for >32 bit machines */
    }
    }
    /**
    * generates a random number on [0,0xffffffff]-interval
    * @private
    */
    private _nextInt32():number {
    var y:number;
    var mag01 = new Array(0x0, Random.MATRIX_A);
    /* mag01[x] = x * MATRIX_A  for x=0,1 */
    if (this.mti >= Random.N) { /* generate N words at one time */
    var kk:number;
    if (this.mti == Random.N + 1)   /* if init_genrand() has not been called, */
    this.init_genrand(5489);
    /* a default initial seed is used */
    for (kk = 0; kk < Random.N - Random.M; kk++) {
    y = (this.mt[kk] & Random.UPPER_MASK) | (this.mt[kk + 1] & Random.LOWER_MASK);
    this.mt[kk] = this.mt[kk + Random.M] ^ (y >>> 1) ^ mag01[y & 0x1];
    }
    for (; kk < Random.N - 1; kk++) {
    y = (this.mt[kk] & Random.UPPER_MASK) | (this.mt[kk + 1] & Random.LOWER_MASK);
    this.mt[kk] = this.mt[kk + (Random.M - Random.N)] ^ (y >>> 1) ^ mag01[y & 0x1];
    }
    y = (this.mt[Random.N - 1] & Random.UPPER_MASK) | (this.mt[0] & Random.LOWER_MASK);
    this.mt[Random.N - 1] = this.mt[Random.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1];
    this.mti = 0;
    }
    y = this.mt[this.mti++];
    /* Tempering */
    y ^= (y >>> 11);
    y ^= (y << 7) & 0x9d2c5680;
    y ^= (y << 15) & 0xefc60000;
    y ^= (y >>> 18);
    return y >>> 0;
    }
    /**
    * generates an int32 pseudo random number
    * @param range: an optional [from, to] range, if not specified the result will be in range [0,0xffffffff]
    * @return {number}
    */
    nextInt32(range:[number, number] = null):number {
    var result = this._nextInt32();
    if (range == null) {
    return result;
    }
    return (result % (range[1] - range[0])) + range[0];
    }
    /**
    * generates a random number on [0,0x7fffffff]-interval
    */
    nextInt31():number {
    return (this._nextInt32() >>> 1);
    }
    /**
    * generates a random number on [0,1]-real-interval
    */
    nextNumber():number {
    return this._nextInt32() * (1.0 / 4294967295.0);
    }
    /**
    * generates a random number on [0,1) with 53-bit resolution
    */
    nextNumber53():number {
    var a = this._nextInt32() >>> 5, b = this._nextInt32() >>> 6;
    return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
    }
    }

    puede que el uso de la siguiente manera:

    var random = new Random(132);
    random.nextInt32(); //return a pseudo random int32 number
    random.nextInt32([10,20]); //return a pseudo random int in range [10,20]
    random.nextNumber(); //return a a pseudo random number in range [0,1]

    compruebe la fuente para más métodos.

  7. 0

    Nota: Este código fue incluido originalmente en la pregunta anterior. En el interés de mantener la pregunta breve y conciso, me he mudado a esta Wiki de la Comunidad de respuesta.

    He encontrado este código pateando y parece que funciona muy bien para obtener un número aleatorio y, a continuación, el uso de la semilla después de esto, pero no estoy muy seguro de cómo la lógica de las obras (por ejemplo, donde el 2345678901, 48271 & 2147483647 números de vino).

    function nextRandomNumber(){
    var hi = this.seed / this.Q;
    var lo = this.seed % this.Q;
    var test = this.A * lo - this.R * hi;
    if(test > 0){
    this.seed = test;
    } else {
    this.seed = test + this.M;
    }
    return (this.seed * this.oneOverM);
    }
    function RandomNumberGenerator(){
    var d = new Date();
    this.seed = 2345678901 + (d.getSeconds() * 0xFFFFFF) + (d.getMinutes() * 0xFFFF);
    this.A = 48271;
    this.M = 2147483647;
    this.Q = this.M / this.A;
    this.R = this.M % this.A;
    this.oneOverM = 1.0 / this.M;
    this.next = nextRandomNumber;
    return this;
    }
    function createRandomNumber(Min, Max){
    var rand = new RandomNumberGenerator();
    return Math.round((Max-Min) * rand.next() + Min);
    }
    //Thus I can now do:
    var letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
    var numbers = ['1','2','3','4','5','6','7','8','9','10'];
    var colors = ['red','orange','yellow','green','blue','indigo','violet'];
    var first = letters[createRandomNumber(0, letters.length)];
    var second = numbers[createRandomNumber(0, numbers.length)];
    var third = colors[createRandomNumber(0, colors.length)];
    alert("Today's show was brought to you by the letter: " + first + ", the number " + second + ", and the color " + third + "!");
    /*
    If I could pass my own seed into the createRandomNumber(min, max, seed);
    function then I could reproduce a random output later if desired.
    */
    • Wow, la RandomNumberGenerator y nextRandomNumber funciones en realidad la fecha todo el camino de regreso a 1996. Se supone que esto es un Lehmer/LCG RNG. Usa algunas inteligente de las matemáticas para realizar modulo aritmética de 32 bits enteros que de otro modo serían demasiado pequeños para contener algunos valores intermedios. La cosa es que JavaScript no implementar 32 bits enteros, pero en lugar de 64 bits carrozas, y dado que la división no es la división entera como la de este código supone el resultado no es una Lehmer generador. Lo que no produce algunos resultados que parecen aleatorios, pero las garantías de un Lehmer generador no se aplican.
    • El createRandomNumber función es una adición posterior, lo hace casi todo mal, más en particular, se crea una instancia de un nuevo generador de números aleatorios cada vez que se llama, lo que significa que las llamadas en rápida sucesión, todos usan el mismo flotador. En el código dado, es casi imposible para 'a' para ser emparejado con cualquier cosa, pero '1' y 'red'.
  8. -2

    OK, aquí está la solución que se establecieron en.

    En primer lugar, crear un valor inicial, el uso de la «newseed()» función. Luego de pasar el valor de la semilla a la «srandom()» función. Por último, el «srandom()» función devuelve un pseudo valor aleatorio entre 0 y 1.

    La crucial poco es que el valor de la semilla se almacena en el interior de una matriz. Si fuera simplemente un integer o float, el valor se sobreescribe cada vez que la función se llama, ya que los valores de enteros, coma flotante, cadenas y así sucesivamente se almacenan directamente en la pila frente a los punteros como en el caso de las matrices y otros objetos. Por lo tanto, es posible que el valor de la semilla para seguir siendo persistente.

    Finalmente, es posible definir el «srandom()» función de que es un método de la «Matemática» del objeto, pero se los dejo para que usted pueda averiguar. 😉

    Buena suerte!

    JavaScript:

    //Global variables used for the seeded random functions, below.
    var seedobja = 1103515245
    var seedobjc = 12345
    var seedobjm = 4294967295 //0x100000000
    //Creates a new seed for seeded functions such as srandom().
    function newseed(seednum)
    {
    return [seednum]
    }
    //Works like Math.random(), except you provide your own seed as the first argument.
    function srandom(seedobj)
    {
    seedobj[0] = (seedobj[0] * seedobja + seedobjc) % seedobjm
    return seedobj[0] / (seedobjm - 1)
    }
    //Store some test values in variables.
    var my_seed_value = newseed(230951)
    var my_random_value_1 = srandom(my_seed_value)
    var my_random_value_2 = srandom(my_seed_value)
    var my_random_value_3 = srandom(my_seed_value)
    //Print the values to console. Replace "WScript.Echo()" with "alert()" if inside a Web browser.
    WScript.Echo(my_random_value_1)
    WScript.Echo(my_random_value_2)
    WScript.Echo(my_random_value_3)

    Lua 4 (personal de mi entorno de destino):

    -- Global variables used for the seeded random functions, below.
    seedobja = 1103515.245
    seedobjc = 12345
    seedobjm = 4294967.295 --0x100000000
    -- Creates a new seed for seeded functions such as srandom().
    function newseed(seednum)
    return {seednum}
    end
    -- Works like random(), except you provide your own seed as the first argument.
    function srandom(seedobj)
    seedobj[1] = mod(seedobj[1] * seedobja + seedobjc, seedobjm)
    return seedobj[1] / (seedobjm - 1)
    end
    -- Store some test values in variables.
    my_seed_value = newseed(230951)
    my_random_value_1 = srandom(my_seed_value)
    my_random_value_2 = srandom(my_seed_value)
    my_random_value_3 = srandom(my_seed_value)
    -- Print the values to console.
    print(my_random_value_1)
    print(my_random_value_2)
    print(my_random_value_3)
    • PS – no estoy familiarizado con el Desbordamiento de Pila, pero ¿por qué no son puestos en orden cronológico?
    • Hola @posfan12 – respuestas a las preguntas son normalmente aparece en el orden de «upvotes» de manera tal que la «crema sube a la cima». Sin embargo, para garantizar la feria de la visualización de las respuestas con la misma puntuación, se muestran en orden aleatorio. Dado que esta era mi pregunta originalmente 😉 que sin duda va a ser así, asegúrese de comprobar a cabo en breve. Si yo (o los otros) ha resultado útil esta respuesta te upvote, y si me parece que es la respuesta «correcta», verá una marca de verificación verde añadido a esta respuesta así. – Bienvenido a StackOverflow!
    • -1 Este LCG implementación de bustos el límite exacto de los números enteros en JavaScript como seedobj[0] * seedobja es probable que resulte en un número mayor que 2^53. El resultado es un limitado rango de salida, y para algunas semillas posiblemente un período muy corto.

Dejar respuesta

Please enter your comment!
Please enter your name here