Conversion Character Mania: Floating Point Output

Perhaps the most complex and bizarre things you can format with printf() conversion characters are floating point numbers. The variety of the options can be overwhelming.

Start with the basics.

Most of the time, you’ll be formatting floating point numbers by using the %f conversion character. That pretty much covers all float and double variables you can imagine.

The problem with %f is that output includes some digits you may not want to see. For example:

#include <stdio.h>

int main()
{
    float a = 123.456;
    double b = 6.022e23;       /* Avogadro's constant */

    printf("%f\n",a);
    printf("%f\n",b);

    return(0);
}

This code, which uses only the plain %f conversion character, displays the following output:

123.456001
602200000000000027262976.000000

You can see the shortcomings of single and double precision values in both lines (although output on your computer may be different): The excess numbers (1 in the first line and 27262976 in the second) are garbage. To curtail such output, you can apply width and precision values to the %f conversion character.

The width value is specified between the % and f characters. It sets the number of characters to be used in the output.

When the sample code is changed so that %15f is used as a conversion character, the output changes to this:

     123.456001
602200000000000027262976.000000

The second line isn’t affected by a width of 15 characters, but the first line is. The width value has no effect when it’s smaller than the size of the number output. To address that shortcoming, a precision value can be specified.

The precision value follows a dot between the % and f characters. The number following the dot sets the number of decimal places to use for output.

Here is the output when the %.2f conversion character is used, which limits output to only two digits after the decimal:

123.46
602200000000000027262976.00

If a width value is needed, it’s specified to the left of the decimal. Here is the output with the %15.2f conversion character:

Again, remember that a large value (the second line) isn’t truncated by a width specification.

         123.46
602200000000000027262976.00

As with integer formatting, you can specify a - right after the % to left-justify the output. A + after the % to place a plus or minus sign before values. And a 0 before the width value to left-pad the output with zeros. (See last week’s lesson for details.)

Floating point output isn’t limited to the %f conversion character. Obviously a very large number, such as 602200000000000027262976.000000, isn’t displayed well regardless of width and precision options.

When the values get really large or teensy tiny, it’s best to use scientific notation for output. That option is handled by the %e or %E placeholders. The difference between them is the size of the letter e in the output:

1.234560e+02
6.022000e+23

These lines were generated by using the %e placeholder instead of %f from the earlier code example. If you change %e to %E you see this output:

1.234560E+02
6.022000E+23

From High School math you’ve long forgotten, the E refers to the position of the decimal in the output. In the first line, the decimal needs to be shifted two places right, which gives the actual value of 123.456. In the second line, the decimal needs to be shifted 23 places to the right, which gives the actual value — a very large number. For very small numbers, a negative E value appears.

Just like %f, you can supply width and precision values with %e and %E. For example, you see this output when the conversion character %15.3e is used for the second number:

      6.022e+23

The %g and %G conversion characters are also used for floating point output. These conversion characters are placeholders for %f, %e, or%E. For small floating point values, %f is used, otherwise %e or %E is substituted. If you use %G then a big E is output for scientific notation, otherwise %g specifies a teensy e.

Here is the output from the sample code when the %g placeholder is used for both printf() statements:

123.456
6.022e+23

Next lesson: Text output formatting.

Leave a Reply