Je contribue actuellement à un système de particules pour notre jeu et je développe des formes d'émetteurs.
Ma distribution aléatoire uniforme le long d'une ligne ou le long d'une zone rectangulaire fonctionne bien - pas de problème.
Mais maintenant, je voudrais avoir quelque chose comme un gradient à 1 dimension dans cette distribution. Cela signifierait par exemple que des valeurs plus faibles sont plus courantes que des valeurs plus élevées.
Je ne sais pas quels termes mathématiques seraient appropriés pour ce problème, donc mes compétences en recherche sont plutôt inutiles avec celui-ci. J'ai besoin de quelque chose de simple sur le plan informatique, car le système de particules doit être efficace.
mathematics
random
distribution
didito
la source
la source
Réponses:
Jetez un oeil à cette image:
Il montre le processus de mise en correspondance d'une valeur (aléatoire) avec une courbe. Supposons que vous générez une valeur aléatoire uniformément distribuée X, allant de 0 à 1. En mappant cette valeur à une courbe - ou, en d'autres termes, en utilisant f (X) au lieu de X - vous pouvez biaiser votre distribution de la manière que vous voulez .
Dans cette image, la première courbe rend les valeurs plus élevées plus probables; le deuxième rend les valeurs plus faibles plus probables; et le troisième fait un cluster de valeurs au milieu. La formule exacte de la courbe n'est pas vraiment importante et peut être choisie à votre guise.
Par exemple, la première courbe ressemble un peu à la racine carrée et la seconde au carré. Le troisième est un peu comme le cube, seulement traduit. Si vous considérez la racine carrée comme trop lente, la première courbe ressemble également à f (X) = 1- (1-X) ^ 2 - une inversion de carré. Ou une hyperbole: f (X) = 2X / (1 + X).
Comme le montre une quatrième courbe, vous pouvez simplement utiliser une table de recherche précalculée. Est laid comme une courbe, mais sera probablement assez bon pour un système de particules.
Cette technique générale est très simple et puissante. Quelle que soit la distribution dont vous avez besoin, imaginez simplement une cartographie de courbe et vous élaborerez une formule en un rien de temps. Ou, si votre moteur a un éditeur, faites simplement un éditeur visuel pour la courbe!
la source
Une explication plus longue:
Si vous avez une distribution de probabilité souhaitée telle que le gradient demandé par @didito, vous pouvez le décrire comme une fonction. Disons que vous voulez une distribution triangulaire, où la probabilité à 0 est 0,0, et que vous voulez choisir un nombre aléatoire de 0 à 1. Nous pourrions l'écrire comme y = x.
L'étape suivante consiste à calculer l'intégrale de cette fonction. Dans ce cas, c'est∫x = 1X2 . Évalué de 0 à 1, c'est ½. Cela a du sens - c'est un triangle avec la base 1 et la hauteur 1, donc sa superficie est de ½.
Vous choisissez ensuite un point aléatoire uniformément de 0 à la zone (½ dans notre exemple). Appelons cela z. (Nous choisissons uniformément dans la distribution cumulative .)
la source
sqrt(random())
ma vie entière mais j'y suis venue empiriquement. Essayer de lier un nombre aléatoire à une courbe, et cela a fonctionné. Maintenant que je suis un peu plus qualifié en mathématiques, savoir pourquoi cela fonctionne est très précieux!Vous obtiendriez probablement une approximation proche de ce que vous voulez en utilisant un système exponentiel.
Faites le x basé sur quelque chose comme 1- (valeur rnd ^) (en supposant que rnd est compris entre 0 et 1) et vous obtiendrez quelques comportements différents de gauche à droite en fonction de ce que vous utilisez. Une valeur plus élevée vous donnera une distribution plus asymétrique
Vous pouvez utiliser un outil graphique en ligne pour obtenir des idées approximatives sur les comportements que différentes équations vous donneront avant de les placer, ou vous pouvez simplement jouer avec les équations directement dans votre système de particules, selon le style qui convient le mieux à vos goûts.
MODIFIER
Pour quelque chose comme un système de particules où le temps CPU par particule est très important, l'utilisation directe de Math.Pow (ou équivalent de langage) peut entraîner une baisse des performances. Si davantage de performances sont souhaitées et que la valeur n'est pas modifiée au moment de l'exécution, envisagez de passer à une fonction équivalente telle que x * x au lieu de x ^ 2.
(Les exposants fractionnaires pourraient être plus problématiques, mais quelqu'un avec une formation en mathématiques plus forte que moi pourrait probablement trouver un bon moyen de créer une fonction d'approximation)
la source
value
, c'est Beta (valeur, 1).Le terme que vous recherchez est
Weighted Random Numbers
, la plupart des algorithmes que j'ai vus utilisent des fonctions trigonométriques, mais je pense que j'ai trouvé un moyen efficace:Créez une table / un tableau / une liste (peu importe) qui contient une valeur de multiplicateur pour la fonction aléatoire. Remplissez-le à la main ou par programme ...
... puis multipliez
random
par une valeur choisie au hasardrandMulti
et enfin par la valeur max de la distribution ...Je pense que cela sera beaucoup plus rapide que l'utilisation
sqrt
ou d'autres fonctions plus complexes sur le plan informatique et permettra des modèles de regroupement plus personnalisés.la source
Je pense que ce que vous demandez, c'est la distribution obtenue en utilisant une fonction de racine carrée.
Cela donnera une distribution dans le champ de dimension unique
[0, 1]
où la probabilité d'une position est équivalente à cette position, c'est-à-dire une "distribution triangulaire".Génération alternative sans racine carrée:
Une racine carrée dans une implémentation optimale est juste quelques commandes de multiplication et de somme sans branches. (Voir: http://en.wikipedia.org/wiki/Fast_inverse_square_root ). Laquelle de ces deux fonctions est la plus rapide peut varier en fonction de la plate-forme et du générateur aléatoire. Sur une plate-forme x86, par exemple, il ne faudrait que quelques branches imprévisibles dans le générateur aléatoire pour ralentir la deuxième méthode.
la source
Utilisez simplement une distribution bêta:
etc.
Les deux paramètres de forme n'ont pas besoin d'être des entiers.
la source
uniform_generator()
appel pargsl_ran_beta(rng, a, b)
. Voir ici: gnu.org/software/gsl/manual/html_node/…Encore plus simple, selon la vitesse de votre générateur aléatoire, vous pouvez simplement générer deux valeurs et les faire la moyenne.
Ou, encore plus simple, où X est le résultat de la RNG, d' abord
double y = double(1/x);
,x = y*[maximum return value of rng];
. Cela pondérera les nombres de façon exponentielle aux nombres inférieurs.Générez et faites la moyenne de plus de valeurs pour augmenter la probabilité de rapprocher les valeurs du centre.
Bien sûr, cela ne fonctionne que pour les distributions de courbes en cloche standard ou leurs versions "pliées" *, mais avec un générateur rapide, cela pourrait être plus rapide et plus simple que d'utiliser diverses fonctions mathématiques comme sqrt.
Vous pouvez trouver toutes sortes de recherches à ce sujet pour les courbes de cloche de dés. En fait, Anydice.com est un bon site qui génère des graphiques pour différentes méthodes de lancer de dés. Bien que vous utilisiez un RNG, la prémisse est la même, tout comme les résultats. C'est donc un bon endroit pour voir la distribution avant même de la coder.
* De plus, vous pouvez "plier" la distribution des résultats le long d'un axe en prenant l'axe et en soustrayant le résultat moyen puis en ajoutant l'axe. Par exemple, vous voulez que les valeurs inférieures soient plus courantes, et disons que vous voulez que 15 soit votre valeur minimale et 35 soit votre valeur maximale, une plage de 20. Ainsi, vous générez et faites la moyenne ensemble de deux valeurs avec une plage de 20 ( deux fois la plage que vous voulez), ce qui donnera une courbe en cloche centrée sur 20 (nous soustrayons cinq à la fin pour déplacer la plage de 20 à 40, à 15 à 35). Prenez les nombres générés X et Y.
Numéro final,
Si zéro est votre minimum, encore mieux, faites-le à la place,
la source