std::normal_distribution în C++

Produce numere aleatorii după distribuția normală (gaussiană, „clopotul”), cu media și abaterea standard date.

Sintaxă
std::normal_distribution<double> dist(medie, abatere_standard);
double x = dist(generator);

Ce face std::normal_distribution

Multe mărimi reale au distribuție normală: înălțimea oamenilor, erori de măsurare, notele la un examen mare. Valorile se adună în jurul mediei, iar cele foarte depărtate sunt rare: circa 68% se află la cel mult o abatere standard de medie și circa 95% la cel mult două.

Fără argumente, media este 0 și abaterea standard este 1. Valorile nu sunt limitate: poate apărea, rar, și un număr foarte depărtat de medie.

Parametri

Parametru Descriere
medie Centrul distribuției.
abatere_standard Cât de împrăștiate sunt valorile (mai mare decât 0).

Ce returnează

La fiecare apel, un double.

Exemple

Exemplul 1: Înălțimi simulate

Media și proporția calculate din 10000 de valori sunt apropiate de cele teoretice (170 cm și aproximativ 68%). Generatorul std::mt19937 cu seed fix produce aceleași numere pe orice compilator, dar modul în care o distribuție le transformă nu este fixat de standard. Rezultatul de mai jos este cel dat de libc++ (Clang); cu GCC sau MSVC, același seed poate da alte valori.

#include <cmath>
#include <print>
#include <random>

int main() {
    std::mt19937 gen(5);
    std::normal_distribution<double> inaltime(170.0, 8.0);

    const int n = 10000;
    double suma = 0;
    int aproape = 0;
    for (int i = 0; i < n; ++i) {
        double h = inaltime(gen);
        suma += h;
        if (std::abs(h - 170.0) <= 8.0) {
            ++aproape;
        }
    }
    std::println("Media: {:.1f} cm", suma / n);
    std::println("Între 162 și 178 cm: {:.0f}%", 100.0 * aproape / n);
}

Rezultat

Media: 170.1 cm
Între 162 și 178 cm: 68%

Exemplul 2: Histogramă text

Generatorul std::mt19937 cu seed fix produce aceleași numere pe orice compilator, dar modul în care o distribuție le transformă nu este fixat de standard. Rezultatul de mai jos este cel dat de libc++ (Clang); cu GCC sau MSVC, același seed poate da alte valori.

#include <cmath>
#include <map>
#include <print>
#include <random>
#include <string>

int main() {
    std::mt19937 gen(42);
    std::normal_distribution<double> nota(7.0, 1.5);

    std::map<long, int> histograma;
    for (int i = 0; i < 2000; ++i) {
        long n = std::lround(nota(gen));
        if (n >= 1 && n <= 10) {
            ++histograma[n];
        }
    }
    for (auto [n, cate] : histograma) {
        std::println("{:>2} {}", n, std::string(cate / 20, '#'));
    }
}

Rezultat

 2 
 3 
 4 ###
 5 ###########
 6 ####################
 7 #########################
 8 ####################
 9 ###########
10 ####

Greșeli frecvente

  • Dai abaterea standard negativă sau 0: comportament nedefinit.
  • Folosești valorile ca note sau vârste fără să le limitezi: distribuția normală poate da și valori sub 1 sau peste 10. Aplică std::clamp sau respinge-le.

Comenzi înrudite

  • std::uniform_real_distribution: Produce numere cu virgulă aleatorii, distribuite uniform în intervalul [a, b).
  • std::mt19937: Generatorul Mersenne Twister: numere pseudo-aleatorii rapide și de calitate, reproductibile cu un seed fix.
  • std::lerp: Interpolare liniară: valoarea aflată la fracțiunea t pe drumul dintre a și b (a + t·(b − a)).