When I run this code:
#include <limits>
#include <cstdio>
#define T double
int main()
{
static const T val = std::numeric_limits<T>::min();
printf( "%g/2 = %g\n", val, val/2 );
}
I would expect to see an unpredictable result. But I get the correct answer:
(16:53) > clang++ test_division.cpp -o test_division
(16:54) > ./test_division
2.22507e-308/2 = 1.11254e-308
How is this possible?
Wiki says this about float : The minimum positive normal value is 2^−126 ≈ 1.18 × 10^−38 and the minimum positive (denormal) value is 2^−149 ≈ 1.4 × 10^−45.
short: min: -32768 max: 32767 int: min: -2147483648 max: 2147483647 long: min: -2147483648 max: 2147483647 float: min: 1.17549e-038 max: 3.40282e+038 double: min: 2.22507e-308 max: 1.79769e+308 long double: min: 2.22507e-308 max: 1.79769e+308 unsigned short: min: 0 max: 65535 unsigned int: min: 0 max: 4294967295 ...
Because min
gives you the smallest normalized value. You can still have smaller denormalized values (see http://en.wikipedia.org/wiki/Denormalized_number).
Historical reasons. std::numeric_limits
was originally built
around the contents of <limits.h>
(where you have e.g.
INT_MIN
) and <float.h>
(where you have e.g. DBL_MIN
).
These two files were (I suspect) designed by different people;
people doing floating point don't need a separate most positive
and most negative value, because the most negative is always the
negation of the most positive, but they do need to know the
smallest value greater than 0. Regretfully, the values have the
same pattern for the name, and std::numeric_limits
ended up
defining the semantics of min
differently depending on
std::numeric_limits<>::is_integer
.
This makes template programming more awkward, you keep having to
do things like std::numeric_limits<T>::is_integer ? std::numeric_limits<T>::min() : -std::numeric_limits<T>::max()
so C++11 adds std::numeric_limits<>::lowest()
, which does
exactly what you'd expect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With