¿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?
Ahora mismo solo estoy usando lo básico Math.random() * 100 + 1
.
javascript
algorithm
random
numbers
Darryl Huffman
fuente
fuente
Respuestas:
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:
JSFiddle: http://jsfiddle.net/797qhcza/1/
fuente
Tienes algunas buenas respuestas aquí que dan soluciones específicas; déjame describirte la solución general. El problema es:
La solución general a este problema es resolver 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 donde 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.
fuente
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 para obtener una distribución con la mayoría de los valores en el medio de su rango.
f(x)=-(1/25)x2+4x
fuente
x
entre 0 y 100 (tomado de esta pregunta ):y = (Math.sin(2 * Math.PI * (x/100 - 1/4)) + 1) / 2
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:
violín: http://jsfiddle.net/kbv39s9w/
fuente
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.
fuente
BellFactor
de 3.Se ve estúpida pero se puede utilizar rand dos veces:
fuente
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.
fuente
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 aún 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.
fuente
¿Qué pasa con el uso de algo como esto:
La forma en que lo codifiqué le permite establecer un par de variables:
bucles = número de
intentos de resultados = número de veces que la función intentará obtener un número entre 40-60 antes de que deje de ejecutarse en el bucle while
Bonificación adicional: ¡Utiliza do while! Impresionante en su mejor momento
fuente
Puede escribir una función que asigna valores aleatorios entre los
[0, 1)
que[1, 100]
según el peso. Considere este ejemplo:Aquí, el valor se
0.95
asigna al valor entre[61, 100]
.De hecho, tenemos
.05 / .1 = 0.5
, que, cuando se asigna a[61, 100]
, produce81
.Aquí está la función:
fuente
Aquí hay una solución ponderada a 3/4 40-60 y 1/4 fuera de ese rango.
fuente
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 del resultado del tipo de 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.
fuente
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:
fuente
fuente
La mejor solución para este 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
Por lo general, empiezo creando una matriz de números (cadenas, pares de coordenadas, etc.) cumpliendo 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.
fuente
Distribución
Solución
Solución Genérica
fuente
Puede usar un número aleatorio auxiliar para generar números aleatorios en 40-60 o 1-100:
fuente
Si puede usar la
gaussian
función, úsela. Esta función devuelve un número normal conaverage 0
ysigma 1
.El 95% de este número está dentro
average +/- 2*sigma
. Tuaverage = 50
ysigma = 5
asífuente
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:
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
Entonces sabemos que necesitamos generar un número en algún lugar entre 0 y 166,666. Luego, 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:Resolver esto para x te da el número aleatorio real que estás buscando, que está garantizado en el rango [0, 100] y una probabilidad mucho mayor de estar cerca del centro que los bordes.
fuente
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:
La información estática inicial, se puede almacenar en caché:
Boundary[n] = Boundary[n - 1] + weigh[n - 1]
yBoundary[0] = 0
. Muestra tieneBoundary = {0, 1, 3, 103, 108}
Generación de números:
N
partir del rango [0, suma de todos los pesos).for (i = 0; i < size(Boundary) && N > Boundary[i + 1]; ++i)
i
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 último.
fuente