Atualmente, estou contribuindo para um sistema de partículas para o nosso jogo e desenvolvendo algumas formas de emissor.
Minha distribuição aleatória uniforme ao longo de uma linha ou ao longo de uma área retangular funciona bem - não há problema.
Mas agora eu gostaria de ter algo como um gradiente unidimensional nesta distribuição. Isso significaria, por exemplo, valores mais baixos são mais comuns que valores mais altos.
Não sei quais seriam os termos matemáticos apropriados para esse problema; portanto, minhas habilidades de pesquisa são bastante inúteis para esse problema. Eu preciso de algo que seja computacionalmente simples, pois o sistema de partículas precisa ser eficiente.
mathematics
random
distribution
didito
fonte
fonte
Respostas:
Dê uma olhada nesta foto:
Ele mostra o processo de mapeamento de um valor (aleatório) para uma curva. Suponha que você gere um valor aleatório uniformemente distribuído X, variando de 0 a 1. Mapeando esse valor para uma curva - ou, em outras palavras, usando f (X) em vez de X - você pode distorcer sua distribuição da maneira que desejar .
Nesta figura, a primeira curva aumenta a probabilidade de valores mais altos; o segundo aumenta a probabilidade de valores mais baixos; e o terceiro faz agrupar valores no meio. A fórmula exata da curva não é realmente importante e pode ser escolhida como você quiser.
Por exemplo, a primeira curva se parece um pouco com a raiz quadrada e a segunda com o quadrado. O terceiro é um pouco parecido com cubo, apenas traduzido. Se você considerar a raiz quadrada muito lenta, a primeira curva também se parecerá com f (X) = 1- (1-X) ^ 2 - uma inversão de quadrado. Ou uma hipérbole: f (X) = 2X / (1 + X).
Como mostra uma quarta curva, você pode simplesmente usar uma tabela de pesquisa pré-computada. É feio como uma curva, mas provavelmente será bom o suficiente para um sistema de partículas.
Essa técnica geral é muito simples e poderosa. Qualquer que seja a distribuição de que você precisa, imagine um mapeamento de curvas e criará uma fórmula rapidamente. Ou, se o seu mecanismo tiver um editor, faça um editor visual para a curva!
fonte
Uma explicação mais longa:
Se você tem uma distribuição de probabilidade desejada , como o gradiente @didito solicitado, pode descrevê-lo como uma função. Digamos que você queira uma distribuição triangular, onde a probabilidade em 0 seja 0,0 e que você queira escolher um número aleatório de 0 a 1. Podemos escrever como y = x.
O próximo passo é calcular a integral desta função. Nesse caso, é . Avaliado de 0 a 1, isso é ½. Isso faz sentido - é um triângulo com base 1 e altura 1, então sua área é ½.∫x=1x2
Você escolhe um ponto aleatório uniformemente de 0 à área (½ no nosso exemplo). Vamos chamar isso de z. (Estamos escolhendo uniformemente a distribuição cumulativa .)
O próximo passo é voltar atrás, para descobrir qual valor de x (vamos chamá-lo de x̂) corresponde a uma área de z. Estamos procurando por , avaliado de 0 a x̂, sendo igual a z. Quando você resolve , obtém .∫x=1x2 1x̂ 2=z x̂ =2z−−√
Neste exemplo, você escolhe z de 0 a ½ e, em seguida, o número aleatório desejado é . Simplificado, você pode escrevê-lo como - exatamente o que o eBusiness recomendou.2z−−√ rand(0,1)−−−−−−−−√
fonte
sqrt(random())
minha vida inteira, mas cheguei a ela empiricamente. Tentando amarrar um número aleatório a uma curva, e funcionou. Agora que tenho um pouco mais de matemática, saber por que funciona é muito valioso!Você provavelmente obteria uma aproximação aproximada do que deseja, utilizando um sistema exponencial.
Faça x baseado em algo como 1- (rnd ^ value) (supondo que rnd esteja entre 0 e 1) e você obterá alguns comportamentos diferentes da inclinação da esquerda para a direita com base no que você usa. Um valor mais alto proporcionará uma distribuição mais distorcida
Você pode usar uma ferramenta gráfica on-line para obter algumas idéias aproximadas sobre os comportamentos que as diferentes equações fornecerão antes de colocá-las, ou você pode simplesmente mexer nas equações diretamente no seu sistema de partículas, dependendo do estilo que mais lhe agrada.
EDITAR
Para algo como um sistema de partículas em que o tempo de CPU por partícula é muito importante, o uso do Math.Pow (ou equivalente de idioma) diretamente pode levar a uma diminuição no desempenho. Se desejar mais desempenho e o valor não estiver sendo alterado no tempo de execução, considere alternar para uma função equivalente, como x * x, em vez de x ^ 2.
(Os expoentes fracionários podem ser mais um problema, mas alguém com uma formação matemática mais forte do que eu provavelmente poderia ter uma boa maneira de criar uma função de aproximação)
fonte
value
, este é Beta (valor, 1).O termo que você está procurando é que a
Weighted Random Numbers
maioria dos algoritmos que vi usam funções trigonométricas, mas acho que descobri uma maneira que será eficiente:Crie uma tabela / matriz / lista (qualquer que seja) que contenha um valor multiplicador para a função aleatória. Preencha-o manualmente ou programaticamente ...
... então multiplique
random
por um escolhido aleatoriamenterandMulti
e, finalmente, pelo valor máximo da distribuição ...Acredito que isso será muito mais rápido do que o uso
sqrt
ou outras funções computacionalmente complexas e permitirá padrões de agrupamento mais personalizados.fonte
Eu acho que o que você pede é a distribuição alcançada usando uma função de raiz quadrada.
Isso fornecerá uma distribuição no campo de dimensão única,
[0, 1]
onde a probabilidade de uma posição é equivalente a essa posição, ou seja, uma "distribuição triangular".Geração alternativa sem quadratura:
Uma raiz quadrada na implementação ideal é apenas alguns comandos de multiplicação e soma sem ramificações. (Veja: http://en.wikipedia.org/wiki/Fast_inverse_square_root ). Qual dessas duas funções é mais rápida pode variar dependendo da plataforma e do gerador aleatório. Em uma plataforma x86, por exemplo, seriam necessárias apenas algumas ramificações imprevisíveis no gerador aleatório para tornar o segundo método mais lento.
fonte
Basta usar uma distribuição Beta:
etc.
Os dois parâmetros de forma não precisam ser inteiros.
fonte
uniform_generator()
ligação porgsl_ran_beta(rng, a, b)
. Veja aqui: gnu.org/software/gsl/manual/html_node/…Ainda mais simples, dependendo da velocidade do seu gerador aleatório, você pode apenas gerar dois valores e fazer a média deles.
Ou, ainda mais simples, onde X é o resultado do RNG, em primeiro lugar
double y = double(1/x);
,x = y*[maximum return value of rng];
. Isso ponderará os números exponencialmente para os números mais baixos.Gere e calcule a média de mais valores para aumentar a probabilidade de obter valores mais próximos do centro.
Obviamente, isso só funciona para distribuições padrão de curvas em sino ou versões "dobradas" *, mas com um gerador rápido, pode ser mais rápido e mais simples do que usar várias funções matemáticas como o sqrt.
Você pode encontrar todo tipo de pesquisa sobre curvas de sino de dados. De fato, o Anydice.com é um bom site que gera gráficos para vários métodos de rolar dados. Embora você esteja usando um RNG, a premissa é a mesma, assim como os resultados. Portanto, é um bom local para ver a distribuição antes mesmo de codificá-la.
* Além disso, você pode "dobrar" a distribuição de resultados ao longo de um eixo, pegando o eixo e subtraindo o resultado médio e adicionando o eixo. Por exemplo, você deseja que valores mais baixos sejam mais comuns e digamos que você queira 15 como seu valor mínimo e 35 como seu valor máximo, um intervalo de 20. Portanto, você gera e calcula a média de dois valores com um intervalo de 20 ( duas vezes o intervalo que você deseja), o que fornecerá uma curva de sino centralizada em 20 (subtraímos cinco no final para alterar o intervalo de 20 para 40 para 15 para 35). Pegue os números gerados X e Y.
Número final,
Se zero é o seu mínimo, melhor ainda, faça isso em vez disso,
fonte