Problem with numeric_limits<double>::digits10

I wrote a program to find the limits and the number of digits for different variable types.

This - int(log10(my_var)) + 1 - works for integer, float, and double.

This - numeric_limits<var_type>::digits10 + 1 only worked for integer.

And neither worked for long double.

Why does numeric_limits<var_type>::digits10 show that float has 6 digits even though the maximum limit has 39 digits? (Same with double and long double)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <limits>
#include <iostream>
#include <math.h>

using namespace std;

int main() {
    int imin = numeric_limits<int>::min();
    int imax = numeric_limits<int>::max();
    float fmin = numeric_limits<float>::min();
    float fmax = numeric_limits<float>::max();
    double dmin = numeric_limits<double>::min();
    double dmax = numeric_limits<double>::max();
    long double ldmin = numeric_limits<long double>::min();
    long double ldmax = numeric_limits<long double>::max();

    cout << imin << ", " << imax << endl;
    cout << int(log10(imax)) + 1 << " digits\n";
    cout << numeric_limits<int>::digits10 + 1 << " digits\n\n";
    cout << fmin << ", " << fmax << endl;
    cout << int(log10(fmax)) + 1 << " digits\n";
    cout << numeric_limits<float>::digits10 + 1 << " digits\n\n";
    cout << dmin << ", " << dmax << endl;
    cout << int(log10(dmax)) + 1 << " digits\n";
    cout << numeric_limits<double>::digits10 + 1 << " digits\n\n";
    cout << ldmin << ", " << ldmax << endl;
    cout << int(log10(ldmax)) + 1 << " digits\n";
    cout << numeric_limits<long double>::digits10 + 1 << " digits\n\n";

    return 0;
}
Last edited on
numeric_limits<float>::max() gives you the largest value that a float can have but that doesn't mean it can store all values that are smaller (not even all integers).

Here is a program that prints the 10 largest values that a float can handle.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <limits>
#include <iostream>
#include <iomanip>
#include <cmath>

int main()
{
	float fvalue = std::numeric_limits<float>::max();

	for (int i = 0; i < 10; ++i)
	{
		std::cout << std::fixed << fvalue << '\n';
		fvalue = std::nextafter(fvalue, 0.0f);
	}
}
340282346638528859811704183484516925440.000000
340282326356119256160033759537265639424.000000
340282306073709652508363335590014353408.000000
340282285791300048856692911642763067392.000000
340282265508890445205022487695511781376.000000
340282245226480841553352063748260495360.000000
340282224944071237901681639801009209344.000000
340282204661661634250011215853757923328.000000
340282184379252030598340791906506637312.000000
340282164096842426946670367959255351296.000000

As you can see from the output there is big leap between the values. Only 6-7 digits stays the same from one value to the next. I don't know how to explain digits10 exactly but it has something to do with this. It tells you something about how much precision you can expect from the type.
digits10, as explained at http://en.cppreference.com/w/cpp/types/numeric_limits/digits10 tells you how many decimal digits can be in a text representation of a number that you convert to the floating-point type and back to decimal text representation of the same length, without changing a single digit in the resulting decimal text.

To take the example from there, if you take the decimal string 8.589973e9 (7 digits), convert it to float, and back to text of the same length, you get 8.589974e9 -- it is the first 7-digit number that doesn't survive text-float-text roundtrip. All 6-digit numbers survive it, which is why numeric_limits<float>::digits10 is 6.

also,
the maximum limit has 39 digits?

39? it takes a lot more decimal digits to print the exact value of some floats

try this one:
1
2
3
4
5
6
7
#include <cstdlib>
#include <iostream>
#include <iomanip>
int main () {
    float f = strtof("0x1.b38fbcp-127", 0);
    std::cout << std::setprecision(250) << f << '\n';
}

output
1.000000075175486824939168507772724780277132519983492503452788921315739882611506317289240541867911815643310546875e-38

http://coliru.stacked-crooked.com/a/ad9fe317354d1bde
Last edited on
Topic archived. No new replies allowed.