std::numeric_limits în C++

Dă proprietățile unui tip numeric: valoarea maximă și minimă, precizia, dacă are semn, infinitul.

Sintaxă
std::numeric_limits<T>::max()
std::numeric_limits<T>::min()
std::numeric_limits<T>::lowest()   // C++11
std::numeric_limits<T>::epsilon()
std::numeric_limits<T>::infinity()

Ce face std::numeric_limits

std::numeric_limits<T> (din <limits>) este înlocuitorul C++ pentru constantele C ca INT_MAX. Funcționează pentru orice tip numeric: numeric_limits<int>::max(), numeric_limits<long long>::max(), numeric_limits<double>::epsilon().

Atenție la tipurile cu virgulă: min() nu este cel mai mic număr negativ, ci cel mai mic număr pozitiv normalizat (aproximativ 2.2e-308). Cel mai mic număr negativ este lowest(). Alte membre utile: digits10 (câte cifre zecimale sigure), is_signed, quiet_NaN().

Parametri

Parametru Descriere
T Tipul numeric: int, unsigned, double etc.

Ce returnează

Valori constante, calculate la compilare.

Exemple

Exemplul 1: Limitele tipurilor întregi

Dimensiunile depind de platformă; rezultatul este pentru macOS pe 64 de biți, procesor ARM (long are 64 de biți, pe Windows are 32; dacă char are semn depinde și el de platformă).

#include <cstdint>
#include <limits>
#include <print>

int main() {
    std::println("int:       {} ... {}", std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
    std::println("unsigned:  {} ... {}", std::numeric_limits<unsigned>::min(), std::numeric_limits<unsigned>::max());
    std::println("long long: max {}", std::numeric_limits<long long>::max());
    std::println("long:      max {}", std::numeric_limits<long>::max());
    std::println("uint8_t:   max {}", std::numeric_limits<std::uint8_t>::max());
    std::println("char cu semn: {}", std::numeric_limits<char>::is_signed);
}

Rezultat

int:       -2147483648 ... 2147483647
unsigned:  0 ... 4294967295
long long: max 9223372036854775807
long:      max 9223372036854775807
uint8_t:   max 255
char cu semn: true

Exemplul 2: Tipurile cu virgulă: min() față de lowest()

#include <limits>
#include <print>

int main() {
    using L = std::numeric_limits<double>;
    std::println("max:      {}", L::max());
    std::println("min:      {}", L::min());
    std::println("lowest:   {}", L::lowest());
    std::println("epsilon:  {}", L::epsilon());
    std::println("digits10: {}", L::digits10);
    std::println("infinity: {}", L::infinity());
}

Rezultat

max:      1.7976931348623157e+308
min:      2.2250738585072014e-308
lowest:   -1.7976931348623157e+308
epsilon:  2.220446049250313e-16
digits10: 15
infinity: inf

Exemplul 3: Valoare de pornire pentru minim

#include <limits>
#include <print>
#include <vector>

int main() {
    std::vector<int> preturi{340, 129, 560, 210};

    int cel_mai_mic = std::numeric_limits<int>::max();
    for (int p : preturi) {
        if (p < cel_mai_mic) {
            cel_mai_mic = p;
        }
    }
    std::println("Cel mai mic preț: {}", cel_mai_mic);
}

Rezultat

Cel mai mic preț: 129

Greșeli frecvente

  • Folosești numeric_limits<double>::min() ca valoare inițială pentru un maxim: este un număr pozitiv foarte mic, nu cel mai mic negativ. Folosește lowest().
  • Aduni 1 la numeric_limits<int>::max(): depășirea unui int cu semn este comportament nedefinit.

Comenzi înrudite

  • std::isnan: Verifică dacă un număr cu virgulă este NaN (rezultat nedefinit) sau infinit (inf).
  • std::bit_width: Returnează câți biți sunt necesari pentru a reprezenta un număr fără semn (0 pentru 0).
  • std::midpoint: Calculează mijlocul dintre două numere (sau pointeri) fără risc de depășire a limitei tipului.