Skip to content

std::numeric_limits

Kirill 'kkm' Katsnelson edited this page Jul 30, 2020 · 2 revisions

Floating point types and std::numeric_limits<>

A tidbit to keep in mind about the messiness of std::numeric_limits<T> when the T is a floating-point type. The functions below return the values of a floating-point type T which are:

Member function Semantics
std::numeric_limits<T>::lowest() the smallest representable value (huge negative number).
std::numeric_limits<T>::denorm_min() the smallest positive representable value (very small positive number).
std::numeric_limits<T>::min() the smallest positive non-denormal number (also a very small positive number).
std::numeric_limits<T>::max() the largest representable value of type T (huge positive number).

In other words,

lowest() <= -max() < -min() <= -denorm_min() < ((T)0) < denorm_min() <= min() < max()
         ^[1]               ^[2]                                     ^[2]

[1] strictly less is an exotic case.
[2] strictly equal is an exotic case.

Also, for regular floats of 32, 64 and 80 bit, and, I think but not sure, for all IEEE-754[-like?] floating point numbers, lowest() == -max() holds. But this is not guaranteed to be true for all float types. The lowest() has been added to C++11 because of this. Also, the values of -denorm_min() and -min() are what you think they should be; no change here, up to an including C++20. The only exception is added for the max(), which is, apparently, in exotic cases, does not produce the most negative representable number when negated.

For reference, the table

T lowest() denorm_min() min() max()
float -3.40282e+38 1.4013e-45 1.17549e-38 3.40282e+38
double -1.79769e+308 4.94066e-324 2.22507e-308 1.79769e+308
long double -1.18973e+4932 3.6452e-4951 3.3621e-4932 1.18973e+4932

and the code to produce it, partly lifted from cppreference.com:

#include <limits>
#include <iostream>

int main()
{
  std::cout << "| `T` | `lowest()` | `denorm_min()` | `min()` | `max()` |\n"
            << "| ---: | ---: | ---: | ---: | ---: |\n"

            << "| float | "
            << std::numeric_limits<float>::lowest()     << " | "
            << std::numeric_limits<float>::denorm_min() << " | "
            << std::numeric_limits<float>::min()        << " | "
            << std::numeric_limits<float>::max()        << " |\n"

            << "| double | "
            << std::numeric_limits<double>::lowest()     << " | "
            << std::numeric_limits<double>::denorm_min() << " | "
            << std::numeric_limits<double>::min()        << " | "
            << std::numeric_limits<double>::max()        << " |\n"

            << "| long double | "
            << std::numeric_limits<long double>::lowest()     << " | "
            << std::numeric_limits<long double>::denorm_min() << " | "
            << std::numeric_limits<long double>::min()        << " | "
            << std::numeric_limits<long double>::max()        << " |\n";

hello

Clone this wiki locally