44 votes

Des nombres aléatoires dont la somme est égale à 100 : Matlab

[Je divise un nombre de population en différentes matrices et je veux tester mon code en utilisant des nombres aléatoires pour le moment].

Question rapide et merci d'avance pour votre aide.

Si j'utilise ;

 100*rand(9,1)

Quelle est la meilleure façon de faire en sorte que la somme de ces 9 nombres soit égale à 100 ?

Je voudrais 9 nombres aléatoires entre 0 et 100 dont le total est de 100.

Existe-t-il une commande intégrée qui permet de faire cela, car je ne la trouve pas.

89voto

Je vois si souvent cette erreur, la suggestion que pour générer des nombres aléatoires avec une somme donnée, il suffit d'utiliser un ensemble aléatoire uniforme, et de les mettre à l'échelle. Mais le résultat est-il vraiment uniformément aléatoire si l'on procède de cette façon ?

Essayez ce test simple en deux dimensions. Générez un énorme échantillon aléatoire, puis mettez-le à l'échelle pour que sa somme soit égale à 1. Je vais utiliser bsxfun pour faire la mise à l'échelle.

xy = rand(10000000,2);
xy = bsxfun(@times,xy,1./sum(xy,2));
hist(xy(:,1),100)

S'ils étaient vraiment uniformément aléatoires, alors la coordonnée x serait uniforme, tout comme la coordonnée y. Toutes les valeurs auraient la même probabilité de se produire. En effet, pour que la somme de deux points soit égale à 1, ils doivent se trouver le long de la ligne qui relie les deux points (0,1), (1,0) dans le plan (x,y). Pour que les points soient uniformes, tout point le long de cette ligne doit avoir la même probabilité.

xy histogram

L'uniformité échoue clairement lorsque j'utilise la solution de mise à l'échelle. Tous les points de cette ligne n'ont PAS la même probabilité. Nous pouvons voir la même chose se produire en 3 dimensions. Vous voyez que dans la figure en 3 dimensions, les points au centre de la région triangulaire sont plus denses. C'est le reflet de la non-uniformité.

xyz = rand(10000,3);
xyz = bsxfun(@times,xyz,1./sum(xyz,2));
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on

xyzplot

Là encore, la solution de la mise à l'échelle simple échoue. Elle ne produit tout simplement PAS de résultats vraiment uniformes sur le domaine d'intérêt.

Peut-on faire mieux ? Eh bien, oui. Une solution simple en 2-d consiste à générer un seul nombre aléatoire qui désigne la distance le long de la ligne reliant les points (0,1) et 1,0).

t = rand(10000000,1);
xy = t*[0 1] + (1-t)*[1 0];
hist(xy(:,1),100)

Uniform x+y = 1

On peut montrer que n'importe quel point de la ligne définie par l'équation x+y = 1, dans le carré unitaire, a maintenant la même probabilité d'avoir été choisi. Ceci est reflété par le bel histogramme plat.

L'astuce suggérée par David Schwartz fonctionne-t-elle en n-dimensions ? Il est clair qu'il fonctionne en 2 dimensions, et la figure ci-dessous suggère qu'il fonctionne en 3 dimensions. Sans avoir réfléchi profondément à la question, je pense que cela fonctionnera pour le cas de base en question, en n-dimensions.

n = 10000;
uv = [zeros(n,1),sort(rand(n,2),2),ones(n,1)];
xyz = diff(uv,[],2);

plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
box on
grid on
view(70,35)

Sort trick

On peut également télécharger la fonction randfixedsum de l'échange de fichiers, la contribution de Roger Stafford. Il s'agit d'une solution plus générale pour générer des ensembles aléatoires véritablement uniformes dans l'hypercube unitaire, avec une somme fixe donnée. Ainsi, pour générer des ensembles aléatoires de points situés dans le cube 3 unitaire, soumis à la contrainte que leur somme soit égale à 1,25...

xyz = randfixedsum(3,10000,1.25,0,1)';
plot3(xyz(:,1),xyz(:,2),xyz(:,3),'.')
view(70,35)
box on
grid on

randfixedsum

71voto

David Schwartz Points 70129

Un moyen simple consiste à choisir 8 numéros aléatoires entre 0 et 100. Ajoutez 0 et 100 à la liste pour obtenir 10 chiffres. Triez-les. Puis indiquez la différence entre chaque paire de nombres successifs. Par exemple, voici 8 nombres aléatoires compris entre 0 et 100 :

96, 38, 95, 5, 13, 57, 13, 20

Alors ajoutez 0 et 100 et triez.

0, 5, 13, 13, 20, 38, 57, 95, 96, 100

Maintenant, soustrayez :

5-0 = 5
13-5 = 8
13-13 = 0
20-13 = 7
38-20 = 18
57-38 = 19
95-57 = 38
96-95 = 1
100-96 = 4

Et voilà, neuf chiffres dont la somme est égale à 100 : 0, 1, 4, 5, 7, 8, 18, 19, 38. Le fait que j'ai eu un zéro et un un était juste un étrange coup de chance.

6voto

Severin Pappadeux Points 4093

Il n'est pas trop tard pour donner la bonne réponse

Parlons de l'échantillonnage de X1...XN dans l'intervalle [0...1] de telle sorte que Sum(X1, ..., XN) soit égal à 1. Vous pouvez ensuite le réévaluer à 100

C'est ce qu'on appelle distribution de Dirichlet et ci-dessous le code pour l'échantillonner. Le cas le plus simple est celui où tous les paramètres sont égaux à 1, alors toutes les distributions marginales pour X1, ..., XN seraient U(0,1). Dans le cas général, avec des paramètres différents de 1, les distributions marginales peuvent avoir des pics.

----------------- tiré de aquí ---------------------

Le Dirichlet est un vecteur de variables aléatoires gamma d'échelle unitaire, normalisées par leur somme. Donc, sans contrôle d'erreur, ceci vous donnera ça :

a = [1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0]; // 9 numbers to sample
n = 10000;
r = drchrnd(a,n)

function r = drchrnd(a,n)
  p = length(a);
  r = gamrnd(repmat(a,n,1),1,n,p);
  r = r ./ repmat(sum(r,2),1,p);

1voto

user2392848 Points 29

Prenez une liste de N - 1 nombres, créez une liste de N + 1 nombres en insérant 0 et 100, triez la liste, et différez-les jusqu'à un total de N nombres.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X