Obteniendo N números aleatorios que la sum es M

Quiero obtener N números aleatorios que la sum de ellos es un valor.

Por ejemplo, supongamos que quiero 5 números aleatorios que su sum es 1

Entonces, una posibilidad válida es:

0.2 0.2 0.2 0.2 0.2 

Otra posibilidad es:

 0.8 0.1 0.03 0.03 0.04 

Y así. Necesito esto para la creación de la matriz de pertenencias del Fuzzy C-means.

Simplemente genere N números aleatorios, calcule su sum, divida cada uno por la sum.

Genere números aleatorios N-1 entre 0 y 1, agregue los números 0 y 1 a la lista, oriéntelos y tome las diferencias de los números adyacentes.

Creo que vale la pena señalar que la respuesta aceptada actualmente no ofrece una distribución uniforme:

“Simplemente genere N números aleatorios, calcule su sum, divida cada uno por la sum”

Para ver esto, veamos el caso N = 2 y M = 1. Este es un caso trivial, ya que podemos generar una lista [x, 1-x], eligiendo x uniformemente en el rango (0,1). La solución propuesta genera un par [x / (x + y), y / (x + y)] donde xey son uniformes en (0,1). Para analizar esto, elegimos algunas z tal que 0

Prob (x / (x + y)

Hice algunos cálculos rápidos y parece que la única solución hasta ahora que parece resultar en una distribución uniforme fue propuesta por Matti Virkkunen :

“Genere números aleatorios N-1 entre 0 y 1, agregue los números 0 y 1 a la lista, oriéntelos y tome las diferencias de los números adyacentes”.

En Java:

 private static double[] randSum(int n, double m) { Random rand = new Random(); double randNums[] = new double[n], sum = 0; for (int i = 0; i < randNums.length; i++) { randNums[i] = rand.nextDouble(); sum += randNums[i]; } for (int i = 0; i < randNums.length; i++) { randNums[i] /= sum * m; } return randNums; } 

Este problema es equivalente al problema de generar números aleatorios con una distribución de Dirichlet . Generar N números positivos que se sumn a un número positivo M, donde cada combinación posible es igualmente probable:

  • Genera N números aleatorios distribuidos exponencialmente. Una forma de generar dicho número puede escribirse como-

     number = -ln(1.0 - RNDU()) 

    donde ln(x) es el logaritmo natural de x RNDU() es un método que devuelve un número aleatorio 0 o mayor y menor que 1 (p. ej., Math.random() JavaScript). Tenga en cuenta que la generación de esos números con una distribución uniforme no es ideal porque se producirá una distribución sesgada de combinaciones de números aleatorios.

  • Divida los números generados de esta manera por su sum.
  • Multiplica cada número por M.

El resultado es N números en una distribución de Dirichlet cuya sum es aproximadamente igual a M (digo “aproximadamente” debido a un error de redondeo).

Este problema también es equivalente al problema de generar números aleatorios uniformemente a partir de un símplex de dimensión n .

Simplemente genere N números aleatorios, calcule su sum, divida cada uno por la sum.

Ampliando la respuesta aceptada de Guillaume , aquí hay una función de Java que hace exactamente eso.

 public static double[] getRandDistArray(int n, double m) { double randArray[] = new double[n]; double sum = 0; // Generate n random numbers for (int i = 0; i < randArray.length; i++) { randArray[i] = Math.random(); sum += randArray[i]; } // Normalize sum to m for (int i = 0; i < randArray.length; i++) { randArray[i] /= sum; randArray[i] *= m; } return randArray; } 

En una ejecución de prueba, getRandDistArray(5, 1.0) devolvió lo siguiente:

 [0.38106150346121903, 0.18099632814238079, 0.17275044310377025, 0.01732932296660358, 0.24786240232602647] 
  1. Genera números aleatorios N-1.
  2. Calcule la sum de dichos números.
  3. Añada la diferencia entre la sum calculada y la sum deseada al conjunto.

Ahora tiene N números aleatorios, y su sum es la sum deseada.

Desafortunadamente, algunas de las respuestas aquí son incorrectas si desea números uniformemente aleatorios. La solución más fácil (y más rápida en muchos idiomas) que garantiza números uniformemente aleatorios es solo

 # This is Python, but most languages support the Dirichlet. import numpy as np np.random.dirichlet(np.ones(n))*m 

donde n es el número de números aleatorios que desea generar m es la sum de la matriz resultante. Este enfoque produce valores positivos y es particularmente útil para generar probabilidades válidas que sumn 1 (let m = 1).

Eres un poco delgado en las limitaciones. Muchos y muchos procedimientos funcionarán.

Por ejemplo, ¿los números se distribuyen normalmente? ¿Uniforme?
Supongo que todos los números deben ser positivos y estar uniformemente distribuidos alrededor de la media, M / N.

Prueba esto.

  1. mean = M / N.
  2. Generar valores N-1 entre 0 y 2 * medio. Este puede ser un número estándar entre 0 y 1, u , y el valor aleatorio es (2 * u-1) * significa crear un valor en un rango apropiado.
  3. Calcule la sum de los valores N-1.
  4. El valor restante es N-sum.
  5. Si el valor restante no se ajusta a las restricciones (0 a 2 * medio), repita el procedimiento.