[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
A biblioteca fornece uma grande coleção de geradores de números aleatórios que pode ser acessados através de uma interface uniforme. Variáveis de ambiente permitem a você selecionar diferentes geradores e sementes durante a execução de forma que você pode facilmente comutar entre geradores sem necessidade de recompilar seu programa. Cada instância de um gerador mantém registros de seu próprio estado, permitindo que os geradores sejam usados em programas multitarefa. Funções adicionais estão disponíveis para transformar números aleatórios uniformes em amostras de distribuições de probabilidade contínua ou discreta tais como a distribuição de Gauss, a log-normal e a de Poisson.
Essas fuinções são declaradas no arquivo de cabeçalho ‘gsl_rng.h’.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Em 1988, Park e Miller escreveram um artigo intitulado “Random number generators: good ones are hard to find.” [Commun. ACM, 31, 1192–1201]. Afortunadamente, alguns excelentes geradores de números aleatórios estão disponíveis, apesar de alguns pobres estarem ainda em uso comum. Você pode estar feliz com o gerador de números aleatórios que acompanha seu sistema operacional no seu computador, mas você deve estar consciente de que da mesma forma que os computadores tornaram-se mais rápidos, as exigências sobre os geradores de números aleatórios aumentaram. Nos dias atuais, uma simulação que chama um gerador de números aleatórios milhões de vezes pode frequentemente terminar antes que você possa descer no salão para ir na máquina de café e voltar.
Uma revisão muito boa de geradores de números aleatórios foi escrita por Pierre L’Ecuyer, no Capítulo 4 do livro: Handbook on Simulation, Jerry Banks, ed. (Wiley, 1997). O capítulo está disponível no formato postscript a partir do sítio ftp do L’Ecuyer’s (veja nas referências). O volume do Knuth sobre Seminumerical Algorithms (originalmente publicado em 1968) reserva 170 páginas para geradores de números aleatórios, e tem recentemente sido atualizado em sua 3a edição (1997). É brilhante, um clássico. Se você não o possui, você deve para a leitura imediatamente, correr até a livraria mais próxima, e comprá-lo.
Um bom gerador de números aleatórios irá satisfazer ambas as propriedades teóricas e estatísticas. Propriedades teóricas são muitas vezes difíceis de se obter (elas requerem matemática verdadeira!), mas uns preferem um gerador de números aleatórios com um período longo, baixa correlação serial, e uma tendência para não “cair principalmente sobre as partes simples.” Testes estatísticos são executados com simulações numéricas. Geralmente, um gerador de números aleatórios é usado para estimar alguma quantidade para a qual a teoria das probabilidades fornece uma resposta exata. Comparação com essa resposta exata fornece uma medida da “aleatoriedade”.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
É importante lembrar que um gerador de números aleatórios não é uma função “real” como seno e cosseno. Diferentemente de funções reais, chamadas sucessivas a um gerador de números aleatórios retorna diferentes valores de retorno. Certamente que é apenas o que você deseja para um gerador de números aleatórios, mas para alcançar esse efeito, o gerador deve manter trilha de algum tipo de variável de “estado”. Algumas vezes esse estado é apenas um inteiro (algumas vezes apenas o valor do número aleatório gerado anteriormente), mas muitas vezes é mais complicado que isso e pode envolver um vetor estático completo de números, possivelmente com alguns índices inclusos. Para usar os geradores de números aleatórios, voce não precisa conhecer os detalhes do que compreende o estado, e como esse estado varia de algoritmo para algoritmo.
A biblioteca de geradores de números aleatórios usa duas estruturas especiais,
gsl_rng_type
que mantém informação estática sobre cada tipo de
gerador e gsl_rng
que descreve uma instância de um gerador
criado a partir de um dado gsl_rng_type
.
As funções descritas nessa seção são declaradas no arquivo de cabeçalho ‘gsl_rng.h’.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Essa função retorna um apontador para a intância mais recentemente criada de um gerador de números aleatórios do tipo T. Por exemplo, o seguinte código cria uma instância do gerador de Tausworthe,
gsl_rng * r = gsl_rng_alloc (gsl_rng_taus);
se não existir memória suficiente para criar o gerador então a
função retorna um apontador nulo e o controlador de erro é chamado com um
código de erro de GSL_ENOMEM
.
O gerador é automaticamente inicializado com a semente padrão,
gsl_rng_default_seed
. Essa semente é zero por padrão mas pode ser mudada
ou diretamente ou através do uso da variável de ambiente GSL_RNG_SEED
(veja seção Variáveis de ambiente de Números Aleatórios).
Os detalhes dos tipos de geradores de números aleatórios disponíveis são descritos mais tarde nesse capítulo.
Essa função inicializa (ou ‘semeia’) o gerador de números aleatórios. Se
o gerador for semeado com o mesmo valor de s em duas diferentes
execuções, o mesmo fluxo de números aleatórios irá ser gerado por sucessivas
chamadas à rotina abaixo. Se diferentes valores de s >= 1 forem fornecidos, então o fluxo gerado de números
aleatórios deve ser completamente diferente. Se a semente s for zero
então a semente padrão da implementação original é usada
ao invés do zero. Por exemplo, o código fonte Fortran original para
o gerador ranlux
usou uma semente de 314159265, e dessa forma fazendo
s igual a zero reproduz-se a semente 314159265 quando usamos
gsl_rng_ranlux
.
Ao usar multiplas sementes com o mesmo gerador, escolha valores de semente maiores que zero para evitar colisões com o ajuste padrão.
Note que a maioria do geradores somente aceita sementes de 32-bit, com valores maiores sendo reduzidos módulo 2^32. Para geradores com pequenos intervalos o maior valor de semente irá ser tipicamente menor que 2^32.
Essa função libera toda a memória associada ao gerador r.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
As seguintes funções retornam números aleatórios distribuidos uniformemente,
ou como inteiros ou como números em ponto flutuante de precisão dupla. Versões modificadas dessa função são usada quando HAVE_INLINE
for definida.
Para obter distribuições não uniformes veja seção Distribuições de Números Aleatórios.
Essa função retorna um inteiro aleatório a partir do gerador r. Os
valores mínimo e máximo dependem do algoritmo usado, mas todos
os inteiros no intervalo [min,max] são igualmente sucetíveis. Os
valores de min e max podem ser determinados usando a função
auxiliar gsl_rng_max (r)
e gsl_rng_min (r)
.
Essa função retorna um número em ponto flutuante de precisão dupla uniformemente
distribuído no intervalo [0,1). O intervalo inclui 0.0 mas exclui 1.0.
O valor é tipicamente obtido dividindo o resultado de
gsl_rng_get(r)
por gsl_rng_max(r) + 1.0
em precisão
dupla. Alguns geradores calculam essa razão internamente de forma que eles
possam fornecer números em ponto flutuante com mais que 32 bits de aleatoriedade
(o número máximo de bits que pode ser portávelmente representado em um simples
unsigned long int
).
Essa função retorna um número em ponto flutuante de precisão dupla
uniformemente distribuído no intervalo (0,1), excluindo ambos 0.0 e 1.0.
O número é obtido por amostragem a partir do gerador com o algorítimo de
gsl_rng_uniform
até que um valor não nulo seja obtido. Você pode usar
essa função se você precisa evitar uma singularidade em 0.0.
Essa função retorna um inteiro aleatório de 0 a n-1 inclusive por meio de ajuste proporcional para baixo e/ou por descarte de amostras a partir do gerador r. Todos os inteiros no intervalo [0,n-1] são produzidos com igual probabilidade. Para geradores com um valor mínimo não nulo uma posição inicial é aplicada de forma que o zero seja retornado com a probabilidade correta.
Note que essa função é pensada para pegar amostras de intervalos menores
que o intervalo do gerador básico. O parâmetro n
deve ser menor que ou igual ao intervalo do gerator r.
Se n for maior que o intervalo do gerador então a função
chama o controlador de erro com um código de erro de GSL_EINVAL
e
retorna zero.
Em particular, essa função não foi pensada para gerar o intervalo completo de
valores inteiros não sinalizados [0,2^32-1]. Ao invés disso
escolha um gerador com o intervalo com um inteiro máximo e zero como valor
mínimo, tal como gsl_rng_ranlxd1
, gsl_rng_mt19937
ou
gsl_rng_taus
, e pegue as amostras diretamente usando
gsl_rng_get
. O intervalo de cada gerador pode ser encontrado usando
as funções auxiliares descritas na próxima seção.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
As seguintes funções fornecem informação sobre um gerador existente. Você deve usá-las preferencialmente ao invés de pegar diretamente os parâmetros do gerador dentro do próprio código fonte do gerador.
Essa função retorna um apontador para o nome do gerador. Por exemplo,
printf ("r é um gerador '%s'\n", gsl_rng_name (r));
irá imprimir alguma coisa como r é um gerador 'taus'
.
gsl_rng_max
retorna o maior valor que gsl_rng_get
pode retornar.
gsl_rng_min
retorna o menor valor que gsl_rng_get
pode retornar. Comumente esse valor é zero. Existe alguns geradores com
algoritmos que não podem retornar zero, e para esses geradores o menor
valor é 1.
Essas funções retornam um apontador para o estado do gerador r e seu tamanho. Você pode usar essa informação para acessar o estado diretamente. Por exemplo, o seguinte código irá escrever o estado de um gerador para um fluxo,
void * state = gsl_rng_state (r); size_t n = gsl_rng_size (r); fwrite (state, n, 1, stream);
Essa função retorna um apontador para vetor estático de todos os tipos de geradores disponíveis, terminado por um apontador nulo. A função deve ser chamada uma vez no início do programa, se for preciso. O seguinte fragmento de código mostra como iteragir sobre o vetor estático de tipos de geradores para mostrar os nomes dos algoritmos disponíveis,
const gsl_rng_type **t, **t0; t0 = gsl_rng_types_setup (); printf ("Available generators:\n"); for (t = t0; *t != 0; t++) { printf ("%s\n", (*t)->name); }
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
A biblioteca permite a você escolher um gerador padrão e a semente padrão a partir das
variáveis de ambiente GSL_RNG_TYPE
e GSL_RNG_SEED
e da
função gsl_rng_env_setup
. Essas três opções de escolha tornam fácil tentar
diferentes geradores e diferentes sementes sem ter que recompilar seu programa.
Essa função lê as variáveis de ambiente GSL_RNG_TYPE
e
GSL_RNG_SEED
e usa seus valores para ajustar as correspondentes
variáveis de biblioteca gsl_rng_default
e
gsl_rng_default_seed
. Essas variáveis globais são definidas como
segue,
extern const gsl_rng_type *gsl_rng_default extern unsigned long int gsl_rng_default_seed
A variável de ambiente GSL_RNG_TYPE
deve ser o nome de um
gerador, tal como taus
ou mt19937
. A variável de
ambiente GSL_RNG_SEED
deve conter o valor de semente desejado. Seu
valor é convertido em um unsigned long int
usando a função da biblioteca C
strtoul
.
Se você não especificar um gerador para GSL_RNG_TYPE
então
gsl_rng_mt19937
é usado como padrão. O valor inicial de
gsl_rng_default_seed
é zero.
Aqui está um programa curto que mostra como criar uma gerador
global usando as variáveis de ambiente GSL_RNG_TYPE
e
GSL_RNG_SEED
,
#include <stdio.h> #include <gsl/gsl_rng.h> gsl_rng * r; /* global generator */ int main (void) { const gsl_rng_type * T; gsl_rng_env_setup(); T = gsl_rng_default; r = gsl_rng_alloc (T); printf ("generator type: %s\n", gsl_rng_name (r)); printf ("seed = %lu\n", gsl_rng_default_seed); printf ("first value = %lu\n", gsl_rng_get (r)); gsl_rng_free (r); return 0; }
Executando o programa sem quaisquer variáveis de ambiente é usado as opções
padrão, um gerador mt19937
com uma semente 0,
$ ./a.outgenerator type: mt19937 seed = 0 first value = 4293858116
Ajustando as duas variáveis pela linha de comando podemos mudar o gerador padrão e a semente,
$ GSL_RNG_TYPE="taus" GSL_RNG_SEED=123 ./a.out GSL_RNG_TYPE=taus GSL_RNG_SEED=123 generator type: taus seed = 123 first value = 2720986350
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Os métodos acima não expõem o ‘estado’ de número aleatório o qual modifica-se de uma chamada para outra. Ter acesso ao ‘estado’ de número aleatório é muitas vezes útil para se gravar e restaurar o estado. Para permitir essas práticas, umas poucas funções mais avançadas são fornecidas. Isso inclui:
Essa função copia o gerador de números aleatórios src para o gerador pré-existente dest, tornando dest uma cópia exata de src. Os dois geradores devem ser do mesmo tipo.
Essa função retorna um apontador para o gerador mais recentemente criado o qual é uma cópia exata do gerador r.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
A biblioteca fornece funções para leitura e escrita do estado do número aleatório em um arquivo como dados binários.
Essa função escreve o estado do número aleatório do gerador de números
aleatórios r para o fluxo stream em formato binário. O
valor de retorno é 0 em caso de sucesso e GSL_EFAILED
se houver um
problema na escrita para o arquivo. Uma vez que os dados são escritos no formato
binário nativo pode não ser portável entre diferentes arquiteturas.
Essa função lê o estado de número aleatório do gerador de números
aleatórios r a partir do fluxo aberto stream em formato binário.
O gerador de números aleatórios r deve ser pré-inicializado com o
tipo correto de gerador de númeos aleatórios uma vez que a informação de tipo não é
gravada. O valor de retorno é 0 em caso de sucesso e GSL_EFAILED
se
houver um problema de leitura a partir do arquivo. Os dados são assumidos
terem sido escritos no formato binário nativo sobre a mesma
arquitetura.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
A função descrita acima não faz referência ao algoritmo atualmente usado. Isso foi feito deliberadamente de forma que você possa mudar algoritmos sem fazer nenhuma alteração no código fonte da sua aplicação. A biblioteca fornece um grande número de geradores de diferentes tipos, incluindo simulação qualitativa de geradores, geradores fornecidos por questões de compatibilidade com outras bilbiotecas e geradores históricos do passado.
Os seguintes geradores são recomendados para uso em simulações. Eles possuem períodos extremamente longos, baixa correlação e obtêm sucesso na maioria dos teste estatísticos. Para a maioria dos códigos seguros de números não relacionados, a segunda geração de geradores RANLUX possui a mais forte demostração de aleatoriedade.
O gerador MT19937 de Makoto Matsumoto e Takuji Nishimura é uma
variante do algoritmo “twisted generalized feedback shift-register”,
e é conhecido como o gerador “Mersenne Twister”. Tem um período de primo
de Mersenne de
2^19937 - 1 (sobre
10^6000) e é
equidistribuído em 623 dimensões. Esse gerador obteve sucesso nos testes
estatísticos de DIEHARD. Esse teste usa 624 palavras de estado por gerador e é
comparável em valocidade a outros geradores. O gerador original usou
uma semente padrão de 4357 e mudar s para zero na
gsl_rng_set
reproduz isso. Versões mais recentes colocaram 5489
como a semente padrão, você pode mudar isso explicitamente via gsl_rng_set
ao invés de usar a semente padrão se você desejar.
Para mais informação veja,
O gerador gsl_rng_mt19937
usa a segunda revisão do
procedimento de semear publicado pelos dois autores acima em 2002. O
procedimento original de semeadura pode causar artefatos espúrios para alguns valores de
semente. Eles estão ainda disponíveis apesar dos geradores alternativos
gsl_rng_mt19937_1999
e gsl_rng_mt19937_1998
.
O gerador ranlxs0
é uma versão de segunda geração do
algoritmo RANLUX de Lüscher, o qual produz “números aleatórios
luxuriosos” (43). Esse gerador fornece saídas de precisão simples (24 bits) em
três níveis de luxúria ranlxs0
, ranlxs1
e ranlxs2
,
em ordem crescente de robustez.
O gerador ranlxs0
uses aritmética em ponto flutuante de precisão dupla internamente e pode ser
significativamente mais rápido que a versão inteira de ranlux
,
particularmente sobre arquiteturas de 64-bit. O período do gerador é
acima de 10^171. O algorítimo tem matematicamente comprovado propriedades e
pode fornecer de forma robusta números não relacionados através de uma fórmula matemática em um dado nível de aleatoriedade.
Os mais altos niveis de luxúria fornecem um incremento aos níveis de não relacionamento entre amostras
como uma margem de segurança adicional.
Note que o intervalo de sementes permitidas para esse gerador é [0,2^31-1]. Maiores valores de semente são empacotados módulo 2^31.
Esses geradores produzem saídas de dupla precisão (48 bits) a partir do
gerador RANLXS. A biblioteca fornece dois níveis de luxúria
ranlxd1
e ranlxd2
, em ordem crescente de robustez.
O gerador ranlux
é uma implementação do algoritmo
original desenvolvido por Lüscher. Usa um
algoritmo lagged-fibonacci-with-skipping para produzir “números aleatórios
luxuriosos”. É um gerador de 24-bit, originalmente pensado para
números em ponto flutuante IEEE de precisão simples. Essa implementação é
baseada em aritmética inteira, enquanto as versões de segunda geração
RANLXS e RANLXD descritas acima fornecem implementações em
ponto flutuante que irão ser mais rápidas sobre muitas plataformas.
O período do gerador é em torno de 10^171. O algoritmo tem matematicamente comprovado propriedades e
pode fornecer números não relacionados em um dado nível de
aleatoriedade. O nível padrão de não relacionamento recomendado por Lüscher
é fornecido por gsl_rng_ranlux
, enquanto gsl_rng_ranlux389
fornece o mais alto nível de aleatoriedade, com todos os 24 bits não relacionados.
Ambos os tipos de gerador usam 24 palavras de estado por gerador.
Para mais informação veja,
Esse é um gerador recursivo múltiplo combinado por L’Ecuyer. Sua sequência é, onde os dois geradores básicos x_n e y_n são, com coeficientes a_1 = 0, a_2 = 63308, a_3 = -183326, b_1 = 86098, b_2 = 0, b_3 = -539608, e módulos m_1 = 2^31 - 1 = 2147483647 e m_2 = 2145483479.
O período desse gerador é lcm(m_1^3-1, m_2^3-1), que é aproximadamente 2^185 (sobre 10^56). Usa 6 palavras de estado por gerador. Para mais informação veja,
Esse é um gerador recursivo múltiplo de quinta ordem por L’Ecuyer, Blouin e Coutre. Sua sequência é, com a_1 = 107374182, a_2 = a_3 = a_4 = 0, a_5 = 104480 e m = 2^31 - 1.
O período desse gerador é algo em torno de 10^46. Usa 5 palavras de estado por gerador. Mais informação pode ser encontrada no seguinte artigo,
Esse é uma gerador de Tausworthe combinado equidistribuído maximamente por
L’Ecuyer. A sequência é,
onde,
módulo calculado
2^32. Nas fórmulas acima
^^
denota “ou-exclusivo”. Note que o algoritmo depende das propriedades
de inteiros sem sinal de 32-bit e tem sido implementado usando uma máscara de bits
de 0xFFFFFFFF
para fazer com que funcione sobre máquinas de 64 bit.
O período desse gerador é 2^88 (sobre 10^26). Usa 3 palavras de estado por gerador. Para mais informação veja,
O gerador gsl_rng_taus2
usa o mesmo algoritmo que
gsl_rng_taus
mas com um procedimento melhorado de semeadura descrito no
artigo,
O gerador gsl_rng_taus2
deve agora ser usado preferêncialmente a
gsl_rng_taus
.
O gerador gfsr4
é como um gerador lagged-fibonacci, e
produz cada número como um somatório ou-exclusivisado
de quatro valores prévios.
Ziff (referenciado abaixo) notes que “é largamente conhecido” que registros two-tap (tais como R250, que é descrito abaixo) tem falhas sérias, a mais óbvia delas sendo a correlação de três pontos que vem a partir da definição de gerador. Boas propriedades matemáticas podem ser derivadas para GFSR’s, e confirma-se numericamente que a alegação de que 4-tap GFSR’s com apropriadamente escolhidas posições iniciais são tão aleatórios quanto puder ser mensurado, usando o teste do autor.
Essa implementação usa os valores sugeridos no exemplo na p392 do artigo de Ziff: A=471, B=1586, C=6988, D=9689.
Se o valor inicial for apropriadamente escolhido (tais como os mostrados acima nessa
implementação), então a sequência é dita para ser máximal; isso significa
que o período é 2^D - 1, onde D é o maior lag.
(É um a menos que 2^D pelo fato de não ser permitido ter todos
zeros no vetor estático ra[]
.) Para essa implementação com
D=9689 que funciona em torno de 10^2917.
Note que a implementação desse gerador usando um inteiro de 32-bit totalizando 32 implementações paralelas de geradores de um-bit. Uma concequência disso é que o período desse gerador de 32-bit é o mesmo que para o gerador de um-bit. Além disso, Essa independência significa que todos modelos de 32-bit são igualmente possíveis, e em particular que 0 é um valor aleatório permitido. (Somos gratos a Heiko Bauke por nos clarificar essas propriedade dos geradores GFSR de números aleatórios.)
Para mais informação veja,
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Os geradores de números aleatórios padrão do Unix rand
, random
e rand48
são fonecidos como parte da GSL. Embora esses
geradores sejam largamente disponíveis individualmente muitas vezes eles não estão todos
disponíveis na mesma plataforma. Isso torna difícil escrever
código portável usando-os e então incluímos o conjunto completo de
geradores Unix na GSL por conveniência. Note que esses geradores
não produzem aleatoriedade de alta qualidade e não são adequados para trabalhos
que precisarem de estatísticas de precisão. Todavia, se você não está medindo
quantidades estatísticas e apenas deseja introduzir alguma variação em
seu programa então esses geradores são suficientemente aceitáveis.
Esse é o gerador rand
do BSD. Sua sequência é
com
a = 1103515245,
c = 12345 and
m = 2^31.
A semente especifica o valor inicial,
x_1. O período desse
gerador é
2^31, e usa 1 palavra de armazenamento por
gerador.
Esses geradores implementam a família random
de funções, um
conjunto de “linear feedback shift register generators” originalmente usado no Unix
BSD. Existem muitas versões de random
em uso atualmente: a
versão origina BSD (e.g. no SunOS4), uma versão libc5 (encontrada nos
sistemas GNU/Linux antigos) e uma versão glibc2. Cada versão usa um
procedimento de semeadura diferente, e dessa forma prosuz diferentes sequências.
As rotinas originais do BSD aceitam um espaço de armazenamento temporário de comprimento variável para o
estado do gerador, com grandes espaços temporários de armazenamento fornecendo aleatoriedade
de alta qualidade. A função random
implementou algoritmos para
comprimentos de espaço temporário de 8, 32, 64, 128 e 256 bytes, e o algoritmo com
o maior comprimento que puder se ajustar no espaço temporário fornecido pelo usuário foi
usado. Por compatibilidade esses algoritmos de geradores adicionais estão disponíveis
com os seguinte nomes,
gsl_rng_random8_bsd gsl_rng_random32_bsd gsl_rng_random64_bsd gsl_rng_random128_bsd gsl_rng_random256_bsd
onde o sufixo numérico indica o comprimento do espaço temporário. A função random
original no BSD usava um espaço temporário padrão de 128-byte e então
gsl_rng_random_bsd
foi feita equivalente a
gsl_rng_random128_bsd
. Correspondentes versões de geradores da
libc5
e da glibc2
estão também disponíveis, com os nomes
gsl_rng_random8_libc5
, gsl_rng_random8_glibc2
, etc.
Esse é o gerador Unix rand48
. Sua sequência é
definido sobre inteiros sem sinal de 48-bit com
a = 25214903917,
c = 11 and
m = 2^48.
A semente especifica os mais altos 32 bits do valor inicial, x_1,
com o mais baixo conjunto de 16 bits ajustado para 0x330E
. A função
gsl_rng_get
retorna os mais altos 32 bits a partir de cada termo da
sequência. Isso não tem um paralelismo direto nas funções
rand48
originais, mas forçando o resultado para o tipo long int
reproduz a saída de mrand48
. A função
gsl_rng_uniform
usa os completos 48 bits do estado interno para retornar
o número de dupla precisão x_n/m, que é equivalente à
função drand48
. Note que algumas versões da bilioteca C GNU
possuem um erro na função mrand48
o que ocasiona a produção de
diferentes resultados (somente os mais baixos 16-bits do valor de retorno foram ajustados).
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Os geradores nessa seção são fornecidos para compatibilidade com as bibliotecas existentes. Se você está convertendo um programa existente para usar a GSL então você pode selecionar esses geradores para verificar sua nova implementação comparando com o original, usando o mesmo gerador de números aleatórios. Após verificar que seu novo programa reproduz o resultado original você pode então mudar para um gerador de melhor qualidade.
Note que a maioria dos geradores nessa seção são baseados em relações congruentes lineares simples, que são o tipo menos sofisticado de gerador. Em particular, congurências lineares possuem reursos pobres quando usadas com um módulo não primo, como a maioria dessas rotinas fazem (e.g. com um expoente de módulo dois, 2^31 ou 2^32). Isso conduz a periodicidades nos menores bits significativos de cada número, com somente os bits mais altos tendo qualquer aleatoriedade. Dessa forma se você deseja produzir um fluxo de bits aleatórios é melhor evitar usar os bits significativos menores.
Esse é o gerador de números aleatórios do CRAY RANF
. Sua sequência é
definido sobre inteiro sem sinal de 48-bit com a = 44485709377909 e
m = 2^48. A semente especifica os mais baixos
32 bits do valor inicial,
x_1, com o mais baixo bit ajustado para
evitar que a semente assuma um valor par. Os mais altos 16 bits de
x_1
são ajustados para 0. Uma consequência desse procedimento é que os pares de sementes
2 e 3, 4 e 5, etc. produzem a mesma sequência.
Esse gerador é compatível com a rotina RANF da CRAY MATHLIB. Produz números em ponto flutuante de precisão dupla o qual deve ser idêntico aos produzidos pela RANF original.
Existe uma sutileza na implementação da semeadura. O estado inicial é revertido em um passo, multiplicando pelo inverso modular de a mod m. Isso é feito para compatibilidade com a implementação original da CRAY.
Note que você pode somente semear o gerador com inteiros acima de 2^32, enquanto a implementação original CRAY usa inteiros grandes não portáveis que podem cobrir todos os 2^48 estados do gerador.
A função gsl_rng_get
retorna os mais altos 32 bits de cada termo
da sequência. A função gsl_rng_uniform
usa os completos 48
bits para retornar o número de precisão dupla x_n/m.
O período desse gerador é 2^46.
Esse é o gerador lagged-fibonacci RANMAR de Marsaglia, Zaman e Tsang. É um gerador de 24-bit, originalmente pensado para números em ponto flutuante IEEE de precisão simples. Foi incluído na biblioteca de física de alta energia CERNLIB.
Esse é o gerador shift-register de Kirkpatrick e Stoll. A sequência é baseada na recorrência onde ^^ denotas “ou-exclusivo”, definido sobre palavras de 32-bit. O período desse gerador está em torno de 2^250 e usa 250 palavras de estado por gerador.
Para mais informação veja,
Essa é uma antiga versão do gerador twisted generalized feedback shift-register, e tem sido substituído pelo desenvolvimento do MT19937. Todavia, ainda é um gerador aceitável por sí mesmo. Tem um período de 2^800 e usa 33 palavras de armazenagem por gerador.
Para mais informação veja,
Esse é o gerador VAX MTH$RANDOM
. Sua sequência é,
com
a = 69069, c = 1 e
m = 2^32. A semente especifica o valor inicial,
x_1. O
período desse gerador é
2^32 e usa 1 palavra de armazenamento por
gerador.
Esse é o gerador de números aleatórios do INMOS Transputer Development system. Sua sequência é, com a = 1664525 e m = 2^32. A semente especifica o valor inicial, x_1.
Esse é o gerador RANDU
da IBM. Sua sequência é
com a = 65539 e
m = 2^31. A
semente especifica o valor inicial,
x_1. O período desse
gerador era somente
2^29. Tem se tornado um libro texto exemplo de um
gerador pobre.
Esse é o gerador “mínimo padrão” de Park e Miller MINSTD, uma congruência linear simples que preocupa-se em evitar a principal armadilha de tais algoritmos. Sua sequência é, com a = 16807 e m = 2^31 - 1 = 2147483647. A semente especifica o valor inicial, x_1. O período desse gerador está em torno de 2^31.
Esse gerador era usado na biblioteca IMSL (subroutina RNUN) e no MATLAB (a função RAND) antigamente. Também algumas vezes conhecido pelo acrônimo “GGL” (Eu não sei o que significa isso).
Para mais informação veja,
Essa é uma reimplementação do gerador de números aleatórios SLATEC de 16-bit
RUNIF. Uma generalização do gerador para 32 bits é fornecida por
gsl_rng_uni32
. O código original está disponível a partir da NETLIB.
Esse é o gerador de números aleatórios RAND da SLATEC. É antigo. O código fonte original está disponível na NETLIB.
Esse é o gerador ZUFALL de séries de Fibonacci com atrazo de Peterson. Sua sequência é,
O código original está disponível a partir da NETLIB. Para mais informação veja,
Esse é um gerador recursivo mĺtiplo de segunda ordem descrito por Knuth em Seminumerical Algorithms, 3rd Ed., page 108. Sua sequência é, com a_1 = 271828183, a_2 = 314159269, e m = 2^31 - 1.
Essa é um gerador recursivo múltiplo de segunda ordem descrito por Knuth
em Seminumerical Algorithms, 3rd Ed., Section 3.6. Knuth
fornece seu código em C. A rotina atualizada gsl_rng_knuthran2002
é a partir da nona impressão revisada e corrige alguns pontos fracos na
versão anterior, o qual é implementada como gsl_rng_knuthran
.
Esses geradores multiplicativos são tomados a partir de Knuth Seminumerical Algorithms, 3rd Ed., página 106–108. Sua sequência é, onde a semente especifica o valor inicial, x_1. Os parâmetros a e m são como segue, Borosh-Niederreiter: a = 1812433253, m = 2^32, Fishman18: a = 62089911, m = 2^31 - 1, Fishman20: a = 48271, m = 2^31 - 1, L’Ecuyer: a = 40692, m = 2^31 - 249, Waterman: a = 1566083941, m = 2^32.
Esse é o gerador de L’Ecuyer–Fishman. É tomado a partir de
Knuth Seminumerical Algorithms, 3a. Ed., página 108. Sua sequência
é,
com m = 2^31 - 1.
x_n e y_n são fornecidos pelos algoritmos
fishman20
e lecuyer21
.
A semente especifica o valor inicial,
x_1.
Esse é o gerador de números aleatórios de Coveyou. É tomado a partir de Knuth Seminumerical Algorithms, 3a. Ed., Seção 3.2.2. Sua sequência é, com m = 2^32. A semente especifica o valor inicial, x_1.
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
A seguinte tabela mostra o desempenho relativo de uma seleção dos
geradores de números aleatórios disponíveis. Os geradores mais rápidos em simulação
de qualidade são taus
, gfsr4
e mt19937
. Os
geradores que oferecem uma qualidade comprovada matematicamente são aqueles
baseados no algoritmo RANLUX.
1754 k ints/sec, 870 k doubles/sec, taus 1613 k ints/sec, 855 k doubles/sec, gfsr4 1370 k ints/sec, 769 k doubles/sec, mt19937 565 k ints/sec, 571 k doubles/sec, ranlxs0 400 k ints/sec, 405 k doubles/sec, ranlxs1 490 k ints/sec, 389 k doubles/sec, mrg 407 k ints/sec, 297 k doubles/sec, ranlux 243 k ints/sec, 254 k doubles/sec, ranlxd1 251 k ints/sec, 253 k doubles/sec, ranlxs2 238 k ints/sec, 215 k doubles/sec, cmrg 247 k ints/sec, 198 k doubles/sec, ranlux389 141 k ints/sec, 140 k doubles/sec, ranlxd2
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O seguinte programa demonstra o uso de um gerador de números aleatórios para produzir números aleatórios uniformes no intervalo [0.0, 1.0),
#include <stdio.h> #include <gsl/gsl_rng.h> int main (void) { const gsl_rng_type * T; gsl_rng * r; int i, n = 10; gsl_rng_env_setup(); T = gsl_rng_default; r = gsl_rng_alloc (T); for (i = 0; i < n; i++) { double u = gsl_rng_uniform (r); printf ("%.5f\n", u); } gsl_rng_free (r); return 0; }
Aqui está a saída d programa,
$ ./a.out0.99974 0.16291 0.28262 0.94720 0.23166 0.48497 0.95748 0.74431 0.54004 0.73995
Os números dependem da semente usada pelo gerador. A semente padrão
pode ser mudada com a variável de ambiente GSL_RNG_SEED
para
produzir um fluxo diferente de números. O gerador propriamente dito pode ser
mudado usando a variável de ambiente GSL_RNG_TYPE
. Aqui está a
saída do programa usando um valor de semente de 123 e o
gerador recursivo múltiplo mrg
,
$ GSL_RNG_SEED=123 GSL_RNG_TYPE=mrg ./a.outGSL_RNG_TYPE=mrg GSL_RNG_SEED=123 0.33050 0.86631 0.32982 0.67620 0.53391 0.06457 0.16847 0.70229 0.04371 0.86374
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
O assunto de geração de números aleatórios e sua verificação de aleatoriedade é revisado extensivamente em Knuth Seminumerical Algorithms.
Informação adicional está disponível no artigo artigo escrito por Pierre L’Ecuyer,
http://www.iro.umontreal.ca/~lecuyer/papers.html no arquivo ‘handsim.ps’.
O código fonte para os testes DIEHARD de geradores de números aleatórios está também disponível online,
Um completo conjunto de geradores de números aleatórios está disponível a partir de NIST,
[ << ] | [ < ] | [ Acima ] | [ > ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Agradecimentos a Makoto Matsumoto, Takuji Nishimura e Yoshiharu Kurita por fazerem o código fonte para seus geradores (MT19937, MM&TN; TT800, MM&YK) disponíveis sob a Licença Pública Geral GNU. Agradecimentos a Martin Lüscher por fornecer notas e código fonte para os geradores RANLXS e RANLXD.
[ << ] | [ >> ] | [Topo] | [Conteúdo] | [Índice] | [ ? ] |
Esse documento foi gerado em 23 de Julho de 2013 usando texi2html 5.0.