web-dev-qa-db-fra.com

Obtention de N nombres aléatoires dont la somme est M

Je veux obtenir N nombres aléatoires dont la somme est une valeur.

Par exemple, supposons que je veuille 5 nombres aléatoires qui totalisent 1.

Ensuite, une possibilité valable est:

0.2 0.2 0.2 0.2 0.2

Une autre possibilité est:

0.8 0.1 0.03 0.03 0.04

Etc. J'en ai besoin pour la création d'une matrice d'appartenance pour les C-means flous.

43
marionmaiden

Réponse courte:

Générez simplement N nombres aléatoires, calculez leur somme, divisez chacun par la somme et multipliez par M.

Réponse plus longue:

La solution ci-dessus ne pas donne une distribution uniforme qui pourrait être un problème selon l'utilisation de ces nombres aléatoires. Une autre méthode proposée par Matti Virkkunen:

Générez N-1 nombres aléatoires entre 0 et 1, ajoutez eux-mêmes les nombres 0 et 1 à la liste, triez-les et prenez les différences des nombres adjacents.

Je ne sais pas si cela donne une distribution uniforme

56
Guillaume

Générez N-1 nombres aléatoires entre 0 et 1, ajoutez eux-mêmes les nombres 0 et 1 à la liste, triez-les et prenez les différences des nombres adjacents.

43
Matti Virkkunen

Je pense qu'il convient de noter que la réponse actuellement acceptée ne donne pas une distribution uniforme:

"Générez simplement N nombres aléatoires, calculez leur somme, divisez chacun par la somme"

Pour voir cela, regardons le cas N = 2 et M = 1. C'est un cas trivial, car nous pouvons générer une liste [x, 1-x], en choisissant x uniformément dans la plage (0,1). La solution proposée génère une paire [x/(x + y), y/(x + y)] où x et y sont uniformes en (0,1). Pour analyser cela, nous choisissons un z tel que 0 <z <0,5 et calculons la probabilité que le premier élément soit plus petit que z. Cette probabilité devrait être z si la distribution était uniforme. Cependant, nous obtenons

Prob (x/(x + y) <z) = Prob (x <z (x + y)) = Prob (x (1-z) <zy) = Prob (x <y(z/(1-z))) = z/(2-2z).

J'ai fait quelques calculs rapides et il semble que la seule solution à ce jour pour que les pommes aboutissent à une distribution uniforme était proposée par Matti Virkkunen :

"Générez N-1 nombres aléatoires entre 0 et 1, ajoutez eux-mêmes les nombres 0 et 1 à la liste, triez-les et prenez les différences des nombres adjacents."

26
Accipitridae

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;
}
4
Vortico

Malheureusement, un certain nombre de réponses ici sont incorrectes si vous souhaitez des nombres aléatoires uniformes. La solution la plus simple (et la plus rapide dans de nombreuses langues) qui garantit des nombres uniformément aléatoires est juste

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

n est le nombre de nombres aléatoires que vous souhaitez générer et m est la somme du tableau résultant. Cette approche produit des valeurs positives et est particulièrement utile pour générer des probabilités valides qui totalisent 1 (soit m = 1).

3
cgnorthcutt

Générez simplement N nombres aléatoires, calculez leur somme, divisez chacun par la somme.

Développant la réponse acceptée par Guillaume , voici une fonction Java qui fait exactement cela.

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;
}

Dans une exécution de test, getRandDistArray(5, 1.0) a renvoyé ce qui suit:

[0.38106150346121903, 0.18099632814238079, 0.17275044310377025, 0.01732932296660358, 0.24786240232602647]
2
Stevoisiak

Ce problème est équivalent au problème de génération de nombres aléatoires avec une distribution de Dirichlet . Pour générer N nombres positifs qui totalisent un nombre positif M, où chaque combinaison possible est également probable:

  • Générez N nombres aléatoires distribués de façon exponentielle. Une façon de générer un tel nombre peut être écrite comme ...

    number = -ln(1.0 - RNDU())
    

    ln(x) est le logarithme naturel de x et RNDU() est une méthode qui renvoie un nombre aléatoire 0 ou supérieur et inférieur à 1 (par exemple, la fonction Math.random()). Notez que la génération de ces nombres avec une distribution uniforme n'est pas idéale car une distribution biaisée de combinaisons de nombres aléatoires en résultera.

  • Divisez les nombres ainsi générés par leur somme.
  • Multipliez chaque nombre par M.

Le résultat est N nombres dans une distribution de Dirichlet dont la somme est approximativement égale à M (je dis "approximativement" à cause d'une erreur d'arrondi).

Ce problème est également équivalent au problème de génération uniforme de nombres aléatoires à partir d'un simplexe à N dimensions .

2
Peter O.
  1. Générez N-1 nombres aléatoires.
  2. Calculez la somme desdits nombres.
  3. Ajoutez la différence entre la somme calculée et la somme souhaitée à l'ensemble.

Vous avez maintenant N nombres aléatoires et leur somme est la somme souhaitée.

1
Yuval

Vous êtes un peu mince sur les contraintes. Beaucoup, beaucoup de procédures fonctionneront.

Par exemple, les nombres sont-ils normalement distribués? Uniforme?
Je suppose que tous les nombres doivent être positifs et uniformément répartis autour de la moyenne, M/N.

Essaye ça.

  1. moyenne = M/N.
  2. Générez des valeurs N-1 entre 0 et 2 * moyenne. Cela peut être un nombre standard entre 0 et 1, , et la valeur aléatoire est (2 * u-1) * signifie pour créer une valeur dans une plage appropriée.
  3. Calculez la somme des valeurs N-1.
  4. La valeur restante est la somme N.
  5. Si la valeur restante ne correspond pas aux contraintes (0 à 2 * moyenne), répétez la procédure.
0
S.Lott