What is the maximum length in chars needed to represent any double value?

When I convert an unsigned 8-bit int to string then I know the result will always be at most 3 chars (for 255) and for an signed 8-bit int we need 4 chars for e.g. "-128".

Now what I'm actually wondering is the same thing for floating-point values. What is the maximum number of chars required to represent any "double" or "float" value as a string?

Assume a regular C/C++ double (IEEE 754) and normal decimal expansion (i.e. no %e printf-formatting).

I'm not even sure if the really small number (i.e. 0.234234) will be longer than the really huge numbers (doubles representing integers)?


Solution 1:

The standard header <float.h> in C, or <cfloat> in C++, contains several constants to do with the range and other metrics of the floating point types. One of these is DBL_MAX_10_EXP, the largest power-of-10 exponent needed to represent all double values. Since 1eN needs N+1 digits to represent, and there might be a negative sign as well, then the answer is

int max_digits = DBL_MAX_10_EXP + 2;

This assumes that the exponent is larger than the number of digits needed to represent the largest possible mantissa value; otherwise, there will also be a decimal point followed by more digits.

CORRECTION

The longest number is actually the smallest representable negative number: it needs enough digits to cover both the exponent and the mantissa. This value is -pow(2, DBL_MIN_EXP - DBL_MANT_DIG), where DBL_MIN_EXP is negative. It's fairly easy to see (and prove by induction) that -pow(2,-N) needs 3+N characters for a non-scientific decimal representation ("-0.", followed by N digits). So the answer is

int max_digits = 3 + DBL_MANT_DIG - DBL_MIN_EXP

For a 64-bit IEEE double, we have

DBL_MANT_DIG = 53
DBL_MIN_EXP = -1023
max_digits = 3 + 53 - (-1023) = 1079

Solution 2:

According to IEEE 754-1985, the longest notation for value represented by double type, i.e.:

-2.2250738585072020E-308

has 24 chars.

Solution 3:

A correct source of information that goes into more detail than the IEEE-754 Specification are these lecture notes from UC Berkely on page 4, plus a little bit of DIY calculations. These lecture slides are also good for engineering students.

Recommended Buffer Sizes

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   16  |  24    |    30    |  45   |

These numbers are based on the following calculations:

Maximum Decimal Count of the Integral Portion

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   9   |   17   |    21    |  36   |

* Quantities listed in decimals.

Decimal counts are based on the formula: At most Ceiling(1 + NLog_10(2)) decimals, where N is the number of bits in the integral portion*.

Maximum Exponent Lengths

| Single| Double | Extended | Quad  |
|:-----:|:------:|:--------:|:-----:|
|   5   |   5    |     7    |   7   |
* Standard format is `e-123`.

Fastest Algorithm

The fastest algorithm for printing floating-point numbers is the Grisu2 algorithm detailed in the research paper Printing Floating-point Numbers Quickly and Accurately. The best benchmark I could find can be found here.

Solution 4:

You can use snprintf() to check how many chars you need. snprintf() returns the number of chars needed to print whatever is passed to it.

/* NOT TESTED */
#include <stdio.h>
#include <stdlib.h>
int main(void) {
    char dummy[1];
    double value = 42.000042; /* or anything else */
    int siz;
    char *representation;
    siz = snprintf(dummy, sizeof dummy, "%f", value);
    printf("exact length needed to represent 'value' "
           "(without the '\\0' terminator) is %d.\n", siz);
    representation = malloc(siz + 1);
    if (representation) {
        sprintf(representation, "%f", value);
        /* use `representation` */
        free(representation);
    } else {
        /* no memory */
    }
    return 0;
}

Note: snprintf() is a C99 function. If a C89 compiler provides it as an extension, it may not do what the above program expects.

Edit: Changed the link to snprintf() to one that actually describes the functionality imposed by the C99 Standard; the description in the original link is wrong.
2013: Changed the link back to POSIX site which I prefer over the site of the first edit.