HOWTO · C++

Como gerar um número de ponto flutuante aleatório em C++

Este artigo demonstra como gerar um número de ponto flutuante aleatório em C++.

Nesta página

Use a biblioteca <random> do C++11 para gerar um valor pseudoaleatório de ponto flutuante dentro de um intervalo escolhido. std::uniform_real_distribution recebe os limites inferior e superior, enquanto um mecanismo aleatório fornece a sequência. Use float ou double conforme a precisão necessária para sua aplicação; use rand apenas ao manter código legado.

Gere um valor de ponto flutuante aleatório com C++11

Este programa completo gera cinco valores no intervalo semiaberto [10, 100). A semente fixa torna a sequência do mecanismo repetível com a mesma implementação da biblioteca padrão, o que é útil durante a depuração. Os valores impressos exatos podem variar entre implementações, pois o algoritmo da distribuição não é especificado de modo a produzir uma sequência portátil.

Execute este exemplo:

#include <iomanip>
#include <iostream>
#include <random>

int main() {
  std::mt19937 engine(2026);
  std::uniform_real_distribution<double> distribution(10.0, 100.0);

  for (int i = 0; i < 5; ++i) {
    std::cout << std::setprecision(10) << distribution(engine) << '\n';
  }
}
78.99481399
96.50696843
96.65823206
73.63312607
11.77415091

O argumento de modelo da distribuição seleciona o tipo do resultado. O padrão é double; os tipos aceitos pela biblioteca padrão são float, double e long double. Escolha um explicitamente para deixar o tipo claro no ponto de chamada: o exemplo usa double, enquanto std::uniform_real_distribution<float> solicita valores float. Os limites são valores reais, e a distribuição exclui o limite superior. Esse intervalo semiaberto é útil para escalar valores em faixas nas quais incluir o limite superior exato faria o valor coincidir com o início da faixa seguinte. Por exemplo, o intervalo de 0.0 a 1.0 pode representar uma proporção normalizada, enquanto o intervalo de 10.0 a 100.0 pode representar uma medida nas unidades escolhidas.

Use float quando sua precisão for suficiente e o uso de armazenamento ou largura de banda for importante; escolha double para obter o equilíbrio habitual entre precisão e faixa de valores. long double está disponível quando sua precisão adicional for útil, embora o ganho dependa da implementação. Sempre que possível, mantenha os valores dos limites alinhados ao tipo da distribuição, especialmente ao alterar o argumento de modelo, para que a faixa pretendida seja fácil de verificar. A distribuição não garante a mesma sequência impressa entre diferentes implementações da biblioteca padrão, mesmo quando a semente do mecanismo é fixa.

Mantenha o mecanismo ativo e reutilize-o ao gerar uma sequência. Criar um mecanismo com uma nova semente para cada valor pode reiniciar ou prejudicar a sequência. Para obter resultados repetíveis, use uma semente fixa, como acima. Para obter uma sequência diferente a cada execução, std::random_device pode fornecer material para a semente quando a implementação oferecer saída não determinística; esse comportamento não é garantido em todos os sistemas. Nenhuma dessas opções torna esse gerador pseudoaleatório de uso geral adequado para valores sensíveis à segurança. A semente inicializa o mecanismo uma vez; ela não serve para criar um mecanismo independente a cada sorteio. Se a aplicação precisar reproduzir resultados entre execuções, registre a semente junto com as outras entradas. Para gerar tokens sensíveis à segurança, use uma fonte criptográfica de números aleatórios em vez desta distribuição e deste mecanismo.

Use rand como uma alternativa legada limitada

A função rand() da biblioteca C retorna um inteiro pseudoaleatório entre 0 e RAND_MAX, inclusive; o valor de RAND_MAX depende da implementação. Para convertê-lo em um intervalo de ponto flutuante, divida por RAND_MAX usando aritmética de ponto flutuante antes de aplicar a escala. Este exemplo mapeia os valores para [10, 100], incluindo o limite superior quando rand() retorna RAND_MAX:

#include <cstdlib>
#include <iostream>

int main() {
  const double lower = 10.0;
  const double upper = 100.0;
  std::srand(2026);

  for (int i = 0; i < 5; ++i) {
    const double value = lower + (upper - lower) *
        (static_cast<double>(std::rand()) / RAND_MAX);
    std::cout << value << '\n';
  }
}
60.2772
88.4741
67.8989
11.5099
83.7273

rand() tem estado e qualidade estatística limitados; uma semente fixa torna este exemplo repetível na mesma implementação da biblioteca C, mas não o torna imprevisível nem seguro. Prefira <random> em código C++ novo, pois essa biblioteca separa o mecanismo da distribuição e permite escolher diretamente o tipo do resultado e o intervalo.