Bojan Nikolic: Numerical and Quantitative Methods in C++

[website home] | [BN Algorithms]

Formatting the output

The program from the previous article looks in pretty good shape to calculate the mean of numbers {1,2,3,4,5}. It will of course calculate the mean of any other set of five numbers fine, but the output may not look terribly pretty. In fact, input and output, is one of the areas where users of C++ get stuck very early on and never move on, so let us tackle that straight away.

Consider the following data set:

const double data[] = {1.9999,2,3,4,5};

The output of the program from the previous article is:

The sum is: 15.9999 and the mean is: 3.19998

Which is correct, but in many situations we may wish to print the result with limited precision; for example, we may wish to output the result to only two decimal places. If you are familiar with Python, you probably will gave come across the formatted printing using the % sign. Similarly, in pure C, programmers use the printf function with the % syntax.

Similarly convenient features are provided in C++ with the excellent Boost libraries.

Improved program: mean_v5

Here is the improved version:

// mean_v5.cpp
// Bojan Nikolic <bojan@bnikolic.co.uk>
// Formatting output

#include <iostream>
#include <boost/format.hpp>

double csum(const double * data,
        size_t n)
{
  double sum =0;
  for (size_t i =0 ; i < n ; ++i )
  {
    sum += data[i];
  }
  return sum;
}

double cmean( const double * data,
          size_t n)
{
  return (csum(data,n)/n);
}

int main(void)
{
  const double data[] = {1.9999,2,3,4,5};
  const size_t n = 5;

  std::cout<<
    boost::format("The sum is: %.2f and the mean is: %.2f")
    % csum(data,n) % cmean(data, n)
    <<std::endl;
}

In the beginning of the program we have added the line:

#include <boost/format.hpp>

Like the other #include line, this has effect of making the C++ compiler aware of what a part of the Boost libraries can do. The file boost/format.hpp includes the declarations of the Format part of Boost, which is the part that allows simpler formatting of output – exactly what we require.

The only other change to the program in the output section, which now uses the boost format routines:

std::cout<<
  boost::format("The sum is: %.2f and the mean is: %.2f")
  % csum(data,n) % cmean(data, n)
  <<std::endl;

How does this work? The expression:

boost::format("The sum is: %.2f and the mean is: %.2f")

creates a boost format string. All of the string will be printed out as it is except for elements of the string which start with the character %. These elements will be replaced by string representations of the variables that follow the boost::format expression. In this case, the next line is :

% csum(data,n) % cmean(data, n)

which means that the first % element in the format string will be replaced by the sum of the data array and that the second % element of the string will be replaced by the mean.

The key to better formatting of the output is in the syntax of the % elements in the format string. In this case, both of these are %.2f, which means print out a real number with precision of two decimal places. The syntax of the various options for % elements is very similar to printf and Python syntax, and is also described in detail in the Format documentation.

How well does it work? This is the output of the revised program:

The sum is: 16.00 and the mean is: 3.20

Two decimal places as expected!

Summary

Input and output always seems tricky. The best solution is to use libraries as much as possible, and when looking for libraries, the Boost collection should always be close to first on your list. In this case the Boost Format library solves our output problem in a very neat and easy way.