Estou tentando escrever uma função C ++ que retornará valores aleatórios gaussianos, considerando suas médias e variações.
Existe uma função de biblioteca rand()
, que retorna números aleatórios entre 0
e RAND_MAX
. RAND_MAX
não possui um valor fixo, mas é garantido que será pelo menos . Seu PDF é uniforme.
Estou usando o Teorema do Limite Central para transformar isso rand()
em uma variável gaussiana. O que estou fazendo exatamente é chamar rand()
um horário especificado pelo usuário, somar seus valores de retorno e mudar sua média para a média especificada pelo usuário.
Na plotagem acima, liguei para meu gerador aleatório gaussiano vezes e ploquei as frequências de seus valores de retorno. Como você vê, sua variação é enorme, pois é criada pela soma de muitos outros valores aleatórios.
Ele retorna com êxito uma variável gaussiana com um PDF gaussiano e com o valor médio especificado. No entanto, o problema é sua variação. Estou parado neste momento, porque não sei como alterar sua variação para o valor especificado pelo usuário.
Este é o meu código (incompleto por enquanto; o parâmetro "Variação" é ignorado):
template <class T>
T Random::GetGaussian(T Mean /*= 0*/, T Variance /*= 1*/)
{
T MeanOfSum = NUM_GAUSSIAN_SUMS / static_cast<T>(2);
T Rand = 0;
for (uint64_t i=0; i<NUM_GAUSSIAN_SUMS; i++)
{
Rand += static_cast<T>(rand()) / RAND_MAX;
}
return Rand - (MeanOfSum - Mean);
}
Suponha que NUM_GAUSSIAN_SUMS
seja 100 e RAND_MAX
seja 32767.
Eu quero mudar a variação da variável aleatória de acordo com o parâmetro da função. Minha pergunta é: como posso alterar a variação dessa variável aleatória? Como eu posso fazer isso?
Respostas:
Seu algoritmo inicial cria uma variável aleatória que é distribuída uniformemente entre 0 e 1. A variação disso é 1/12. Se você somar
NUM_GAUSSIAN_SUMS
instâncias disso, a variação seráNUM_GAUSSIAN_SUMS/12
. Para obter uma variação de destinoV
, é necessário multiplicar a variável aleatória somada porsqrt(V*12/NUM_GAUSSIAN_SUMS)
.Como observação lateral, um modelo funcionará razoavelmente bem para flutuadores e duplos, mas haverá problemas numéricos significativos com qualquer tipo de ponto fixo.
fonte
Por multiplicação, é claro. A variação de , onde é a constante multiplicativa e é a variável aleatória, é a variância de .c X c 2 XcX c X c2 X
fonte
Existe ainda outra maneira!
Pense nisso, e se você quisesse alguma outra distribuição em oposição à gaussiana? Nesse caso, você realmente não poderia usar o teorema do limite central; como você resolve isso?
Existe uma maneira de converter variáveis aleatórias uniformes em PDF arbitrário. Esse método é chamado de método de transformação inversa
Se estiver uniformemente distribuído no intervalo (0, 1), entãoU[0−1]
tem o cdf .FX(x)
Portanto, tudo o que você precisa fazer é aplicar a função CDF inversa à variável que você recuperou da amostra do rv uniforme.
Além disso, diferentemente dos métodos anteriores - isso não exigirá nenhuma iteração e não dependerá de quantas iterações serão feitas para tornar os resultados mais próximos do Gaussian.
Aqui está uma das referências que fornece uma prova disso.
fonte