sirve repetir que para numeros numero entre entero aleatorios aleatorio javascript algorithm random numbers

javascript - repetir - Obtenga un número aleatorio enfocado en el centro



numeros aleatorios html javascript (20)

¿Es posible obtener un número aleatorio entre 1-100 y mantener los resultados principalmente dentro del rango 40-60? Quiero decir, rara vez saldrá de ese rango, pero quiero que esté principalmente dentro de ese rango ... ¿Es posible con JavaScript / jQuery?

En este momento solo estoy usando el Math.random() * 100 + 1 básico Math.random() * 100 + 1 .


¿Qué pasa con el uso de algo como esto:

var loops = 10; var tries = 10; var div = $("#results").html(random()); function random() { var values = ""; for(var i=0; i < loops; i++) { var numTries = tries; do { var num = Math.floor((Math.random() * 100) + 1); numTries--; } while((num < 40 || num >60) && numTries > 1) values += num + "<br/>"; } return values; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="results"></div>

La forma en que lo he codificado le permite establecer un par de variables:
bucles = número de resultados
tries = número de veces que la función intentará obtener un número entre 40-60 antes de que deje de ejecutarse en el ciclo while

Bonificación adicional: ¡Utiliza do while! Impresionante en su mejor momento


Aquí hay una solución ponderada a 3/4 40-60 y 1/4 fuera de ese rango.

function weighted() { var w = 4; // number 1 to w var r = Math.floor(Math.random() * w) + 1; if (r === 1) { // 1/w goes to outside 40-60 var n = Math.floor(Math.random() * 80) + 1; if (n >= 40 && n <= 60) n += 40; return n } // w-1/w goes to 40-60 range. return Math.floor(Math.random() * 21) + 40; } function test() { var counts = []; for (var i = 0; i < 2000; i++) { var n = weighted(); if (!counts[n]) counts[n] = 0; counts[n] ++; } var output = document.getElementById(''output''); var o = ""; for (var i = 1; i <= 100; i++) { o += i + " - " + (counts[i] | 0) + "/n"; } output.innerHTML = o; } test();

<pre id="output"></pre>


Claro que es posible. Haz un aleatorio 1-100. Si el número es <30, genere un número en el rango 1-100 si no se genera en el rango 40-60.


Distribución

5% for [ 0,39] 90% for [40,59] 5% for [60,99]

Solución

var f = Math.random(); if (f < 0.05) return random(0,39); else if (f < 0.95) return random(40,59); else return random(60,99);

Solución Genérica

random_choose([series(0,39),series(40,59),series(60,99)],[0.05,0.90,0.05]); function random_choose (collections,probabilities) { var acc = 0.00; var r1 = Math.random(); var r2 = Math.random(); for (var i = 0; i < probabilities.length; i++) { acc += probabilities[i]; if (r1 < acc) return collections[i][Math.floor(r2*collections[i].length)]; } return (-1); } function series(min,max) { var i = min; var s = []; while (s[s.length-1] < max) s[s.length]=i++; return s; }


Hay muchas formas diferentes de generar tales números aleatorios. Una forma de hacerlo es calcular la suma de múltiples números uniformemente aleatorios. Cuántos números aleatorios sumes y cuál es su rango determinará cómo se verá la distribución final.

Cuantos más números sumes, más sesgará hacia el centro. El uso de la suma de 1 número aleatorio ya se propuso en su pregunta, pero como verá, no está sesgado hacia el centro del rango. Otras respuestas han propuesto usar la suma de 2 números aleatorios o la suma de 3 números aleatorios .

Puede obtener aún más sesgo hacia el centro del rango tomando la suma de más números aleatorios. En el extremo, podría tomar la suma de 99 números aleatorios, cada uno de los cuales era 0 o 1. Esa sería una distribución binomial. (Las distribuciones binomiales pueden verse en cierto sentido como la versión discreta de las distribuciones normales). En teoría, esto puede abarcar todo el rango, pero tiene tanta inclinación hacia el centro que nunca se debe esperar que llegue a los puntos finales.

Este enfoque significa que puede ajustar la cantidad de sesgo que desea.


La forma más sencilla sería generar dos números aleatorios del 0 al 50 y sumarlos.

Esto da una distribución sesgada hacia 50, de la misma manera tirando dos sesgos de dados hacia 7.

De hecho, al usar un mayor número de "dados" (como sugiere @Falco) , puede hacer una aproximación más cercana a una curva de campana:

function weightedRandom(max, numDice) { var num = 0; for (var i = 0; i < numDice; i++) { num += Math.random() * (max/numDice); } return num; }

JSFiddle: http://jsfiddle.net/797qhcza/1/


La mejor manera de hacerlo es generar un número aleatorio que se distribuya equitativamente en un determinado conjunto de números, y luego aplicar una función de proyección al conjunto entre 0 y 100 donde la proyección es más probable que llegue a los números que desea.

Por lo general, la forma matemática de lograr esto es trazar una función de probabilidad de los números que desea. Podríamos usar la curva de campana, pero en aras de un cálculo más fácil, simplemente trabajemos con una parábola invertida.

Hagamos una parábola de modo que sus raíces estén en 0 y 100 sin sesgarla. Obtenemos la siguiente ecuación:

f(x) = -(x-0)(x-100) = -x * (x-100) = -x^2 + 100x

Ahora, toda el área bajo la curva entre 0 y 100 es representativa de nuestro primer conjunto donde queremos que se generen los números. Allí, la generación es completamente al azar. Entonces, todo lo que necesitamos hacer es encontrar los límites de nuestro primer conjunto.

El límite inferior es, por supuesto, 0. El límite superior es la integral de nuestra función en 100, que es

F(x) = -x^3/3 + 50x^2 F(100) = 500,000/3 = 166,666.66666 (let''s just use 166,666, because rounding up would make the target out of bounds)

Entonces sabemos que necesitamos generar un número en algún lugar entre 0 y 166,666. Entonces, simplemente necesitamos tomar ese número y proyectarlo en nuestro segundo conjunto, que está entre 0 y 100.

Sabemos que el número aleatorio que generamos es parte integral de nuestra parábola con una entrada x entre 0 y 100. Eso significa que simplemente tenemos que suponer que el número aleatorio es el resultado de F (x) y resolver para x.

En este caso, F (x) es una ecuación cúbica, y en la forma F(x) = ax^3 + bx^2 + cx + d = 0 , las siguientes afirmaciones son verdaderas:

a = -1/3 b = 50 c = 0 d = -1 * (your random number)

Resolver esto para x le da el número aleatorio real que está buscando, que se garantiza que está en el rango [0, 100] y una probabilidad mucho mayor de estar cerca del centro que los bordes.


La mejor solución para este mismo problema es la propuesta por BlueRaja: Danny Pflughoeft, pero creo que también vale la pena mencionar una solución algo más rápida y más general.

Cuando tengo que generar números aleatorios (cadenas, pares de coordenadas, etc.) que satisfacen los dos requisitos de

  1. El conjunto de resultados es bastante pequeño. (no mayor a 16K números)
  2. El conjunto de resultados es discreto. (como solo números enteros)

Por lo general, empiezo creando una matriz de números (cadenas, pares de coordenadas, etc.) que cumplen el requisito (en su caso: una matriz de números que contiene los más probables varias veces), luego elijo un elemento aleatorio de esa matriz. De esta manera, solo tiene que llamar a la costosa función aleatoria una vez por artículo.


Necesitaba resolver este problema hace unos años y mi solución fue más fácil que cualquiera de las otras respuestas.

Genere 3 randoms entre los límites y los promedié. Esto empuja el resultado hacia el centro pero deja completamente posible llegar a las extremidades.


Ok, entonces decidí agregar otra respuesta porque sentí que mi última respuesta, así como la mayoría de las respuestas aquí, usan algún tipo de medio estadístico para obtener un retorno de resultado de tipo curva de campana. El código que proporciono a continuación funciona de la misma manera que cuando lanzas un dado. Por lo tanto, es más difícil obtener 1 o 99, pero es más fácil obtener 50.

var loops = 10; //Number of numbers generated var min = 1, max = 50; var div = $("#results").html(random()); function random() { var values = ""; for (var i = 0; i < loops; i++) { var one = generate(); var two = generate(); var ans = one + two - 1; var num = values += ans + "<br/>"; } return values; } function generate() { return Math.floor((Math.random() * (max - min + 1)) + min); }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <div id="results"></div>


Podría hacer algo como configurar una "oportunidad" para que el número se deje "fuera de los límites". En este ejemplo, una probabilidad del 20% de que el número sea 1-100, de lo contrario, 40-60:

$(function () { $(''button'').click(function () { var outOfBoundsChance = .2; var num = 0; if (Math.random() <= outOfBoundsChance) { num = getRandomInt(1, 100); } else { num = getRandomInt(40, 60); } $(''#out'').text(num); }); function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } });

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <button>Generate</button> <div id="out"></div>

violín: http://jsfiddle.net/kbv39s9w/


Puede escribir una función que asigne valores aleatorios entre [0, 1) a [1, 100] según el peso. Considere este ejemplo:

Aquí, el valor 0.95 asigna al valor entre [61, 100] .
De hecho, tenemos .05 / .1 = 0.5 , que, cuando se asigna a [61, 100] , produce 81 .

Aquí está la función:

/* * Function that returns a function that maps random number to value according to map of probability */ function createDistributionFunction(data) { // cache data + some pre-calculations var cache = []; var i; for (i = 0; i < data.length; i++) { cache[i] = {}; cache[i].valueMin = data[i].values[0]; cache[i].valueMax = data[i].values[1]; cache[i].rangeMin = i === 0 ? 0 : cache[i - 1].rangeMax; cache[i].rangeMax = cache[i].rangeMin + data[i].weight; } return function(random) { var value; for (i = 0; i < cache.length; i++) { // this maps random number to the bracket and the value inside that bracket if (cache[i].rangeMin <= random && random < cache[i].rangeMax) { value = (random - cache[i].rangeMin) / (cache[i].rangeMax - cache[i].rangeMin); value *= cache[i].valueMax - cache[i].valueMin + 1; value += cache[i].valueMin; return Math.floor(value); } } }; } /* * Example usage */ var distributionFunction = createDistributionFunction([ { weight: 0.1, values: [1, 40] }, { weight: 0.8, values: [41, 60] }, { weight: 0.1, values: [61, 100] } ]); /* * Test the example and draw results using Google charts API */ function testAndDrawResult() { var counts = []; var i; var value; // run the function in a loop and count the number of occurrences of each value for (i = 0; i < 10000; i++) { value = distributionFunction(Math.random()); counts[value] = (counts[value] || 0) + 1; } // convert results to datatable and display var data = new google.visualization.DataTable(); data.addColumn("number", "Value"); data.addColumn("number", "Count"); for (value = 0; value < counts.length; value++) { if (counts[value] !== undefined) { data.addRow([value, counts[value]]); } } var chart = new google.visualization.ColumnChart(document.getElementById("chart")); chart.draw(data); } google.load("visualization", "1", { packages: ["corechart"] }); google.setOnLoadCallback(testAndDrawResult);

<script src="https://www.google.com/jsapi"></script> <div id="chart"></div>


Puede usar un número aleatorio auxiliar para generar números aleatorios en 40-60 o 1-100:

// 90% of random numbers should be between 40 to 60. var weight_percentage = 90; var focuse_on_center = ( (Math.random() * 100) < weight_percentage ); if(focuse_on_center) { // generate a random number within the 40-60 range. alert (40 + Math.random() * 20 + 1); } else { // generate a random number within the 1-100 range. alert (Math.random() * 100 + 1); }


Recomiendo usar la distribución beta para generar un número entre 0-1, luego escalarlo. Es bastante flexible y puede crear muchas formas diferentes de distribuciones.

Aquí hay una muestra rápida y sucia:

rbeta = function(alpha, beta) { var a = 0 for(var i = 0; i < alpha; i++) a -= Math.log(Math.random()) var b = 0 for(var i = 0; i < beta; i++) b -= Math.log(Math.random()) return Math.ceil(100 * a / (a+b)) }


Si puede usar la función gaussian , gaussian . Esta función devuelve un número normal con un average 0 y sigma 1 .

El 95% de este número está dentro del average +/- 2*sigma . Su average = 50 y sigma = 5 entonces

randomNumber = 50 + 5*gaussian()


Tienes algunas buenas respuestas aquí que dan soluciones específicas; déjame describirte la solución general. El problema es:

  • Tengo una fuente de números aleatorios distribuidos más o menos uniformemente entre 0 y 1.
  • Deseo producir una secuencia de números aleatorios que sigan una distribución diferente.

La solución general a este problema es calcular la función cuantil de su distribución deseada y luego aplicar la función cuantil a la salida de su fuente uniforme.

La función cuantil es la inversa de la integral de su función de distribución deseada. La función de distribución es la función en la que el área debajo de una porción de la curva es igual a la probabilidad de que el elemento elegido al azar esté en esa porción.

Doy un ejemplo de cómo hacerlo aquí:

http://ericlippert.com/2012/02/21/generating-random-non-uniform-data/

El código allí está en C #, pero los principios se aplican a cualquier lenguaje; Debería ser sencillo adaptar la solución a JavaScript.


Tomar matrices de números, etc. no es eficiente. Debe tomar una asignación que tome un número aleatorio entre 0 y 100 y asigna la distribución que necesita. Entonces, en su caso, podría tomar f(x)=-(1/25)x 2 +4x para obtener una distribución con la mayoría de los valores en el medio de su rango.


Esta respuesta es realmente buena . Pero me gustaría publicar instrucciones de implementación (no estoy en JavaScript, así que espero que entiendan) para diferentes situaciones.

Suponga que tiene rangos y pesos para cada rango:

ranges - [1, 20], [21, 40], [41, 60], [61, 100] weights - {1, 2, 100, 5}

La información estática inicial, se puede almacenar en caché:

  1. Suma de todos los pesos (108 en muestra)
  2. Rango de selección de límites. Básicamente esta fórmula: Boundary[n] = Boundary[n - 1] + weigh[n - 1] y Boundary[0] = 0 . La muestra tiene Boundary = {0, 1, 3, 103, 108}

Generación de números:

  1. Genere un número aleatorio N del rango [0, suma de todos los pesos).
  2. for (i = 0; i < size(Boundary) && N > Boundary[i + 1]; ++i)
  3. Tome el rango y genere un número aleatorio en ese rango.

Nota adicional para optimizaciones de rendimiento. No es necesario ordenar los rangos ni en orden ascendente ni descendente, por lo que para un rango de búsqueda de rango más rápido que tenga el mayor peso debe ir primero y uno con el menor peso debe ir al final.


Parece estúpido pero puedes usar rand dos veces:

var choice = Math.random() * 3; var result; if (choice < 2){ result = Math.random() * 20 + 40; //you have 2/3 chance to go there } else { result = Math.random() * 100 + 1; }


var randNum; // generate random number from 1-5 var freq = Math.floor(Math.random() * (6 - 1) + 1); // focus on 40-60 if the number is odd (1,3, or 5) // this should happen %60 of the time if (freq % 2){ randNum = Math.floor(Math.random() * (60 - 40) + 40); } else { randNum = Math.floor(Math.random() * (100 - 1) + 1); }