Chapter 4B

NUMERIC DATA TYPES

AND FORMATTING

As discussed in Chapter 1, a variable is a name assigned to a first byte of the necessary memory to store a value. However the compiler needs to know size of the memory to reserve to hold the value beginning with that memory location. This is where the type comes in. In a 16-bit computer for an integer 2 bytes are used, float 4 bytes, double 8 bytes, and character and bool 1 byte each. The size of memory reserved by the compiler you are using can be determined by the operator sizeof.

For example, cout << sizeof(x); if x is an integer, either a 2 or 4 will be displayed.

Some of these types can be signed or unsigned. Unsigned can hold much larger number. For example, in a signed integer variable the range of values are -32,768 to 32,767. In an unsigned integer this range is from 0 to 65,535. Float and double are real numbers, the difference is in their precision. The major differences between integers and real numbers are as follows.

    1. integers are ordinal; an integer has a specific predecessor and successor. They are represented precisely in the computer in binary. Negative numbers are represented in two's complement.
    2. Real numbers are not ordinal. They have decimal portions. They are represented in the computer as two portions, mantissa and exponent. Real numbers cannot be represented exactly in the computer; they are approximations only. Therefore, two real numbers cannot be checked for equality. Truncation errors occur when two real numbers are multiplied or divided.

When outputing a real number it is often necessary to indicate the number of decimal digits we want to display. When dealing with dollars there is little reason to go beyond two decimal points. We can use setprecision(n) which is a manipulator available from <iomanip.h>, to indicate the decimal precision we require. For example cout << setprecision(2) << dollars; will display dollars with 2 decimal point precision. The last decimal digit will be rounded of. Consider the following program:

Program 6-1

#include <iostream.h>

#include <iomanip.h>

int main()

{

cout << 28 <<" " <<28*1.128 <<endl;

cout << 123 << " " <<123*11.228 <<endl;

return 0;

}

 

Program Run 6-1:

28 31.584

123 1381.04

Press any key to continue

The columns in the above program do not line up. Now consider the following program and its formatted output.. The integers line up. But even though we used the setprecion(2), the real numbers are displayed differently. Obviously for real numbers the setprecision alone is not enough. In Program 6-3, setw, setiosflags and setprecision are added. This seems to have fixed the problem. Here the ios::fixed causes the real number to be output in fixed point format instead of exponential format.

Program 6-2

#include <iostream.h>

#include <iomanip.h>

int main()

{

cout << setw(5)<<28 <<" " <<setprecision(2) << 28*1.128 <<endl;

cout << setw(5) <<123 << " " <<setprecision(2) << 123*11.228 <<endl;

return 0;

}

 

Program Run 6-2

28 32

123 1.4e+003

Press any key to continue

 

Program 6-3.

#include <iostream.h>

#include <iomanip.h>

int main()

{

cout << setw(5)<<28

<<setw(10)<<setiosflags(ios::fixed) <<setprecision(2) << 28*1.128 <<endl;

cout << setw(5) <<123

<<setw(10)<<setiosflags(ios::fixed) <<setprecision(2) << 123*11.228 <<endl;

return 0;

}

 

Program Run 6-3.

28 31.58

123 1381.04

Press any key to continue.

At the end of this chapter a more complete discussion is presented on this topic. In chapter 1 you were introduced to the escape character set \n to give a new line. There are other useful escape sequences. Here are some:

\b move back one space

\f move to next page

\t tab over

\\ prints a back slash

\' prints a single quote.

 

 

 

 

 

IOMANIP provides several input and output format manipulators. Here is a summary of the most commonly used ones. An explanation of numeric formatting also is given. This section is obtained from the Visual C++ help.

SETIOSFLAGS

ios::skipws Skip white space on input.

ios::left Left-align values; pad on the right with the fill character.

ios::right Right-align values; pad on the left with the fill character (default alignment).

ios::internal Add fill characters after any leading sign or base indication, but before the value.

ios::dec Format numeric values as base 10 (decimal) (default radix).

ios::oct Format numeric values as base 8 (octal).

ios::hex Format numeric values as base 16 (hexadecimal).

ios::showbase Display numeric constants in a format that can be read by the C++ compiler.

ios::showpoint Show decimal point and trailing zeros for floating-point values.

ios::uppercase Display uppercase A through F for hexadecimal values and E for scientific values.

ios::showpos Show plus signs (+) for positive values.

ios::scientific Display floating-point numbers in scientific format.

ios::fixed Display floating-point numbers in fixed format.

ios::unitbuf Cause ostream::osfx to flush the stream after each insertion. By default, cerr is unit buffered.

ios::stdio Cause ostream::osfx to flush stdout and stderr after each insertion.

 

Using Insertion Operators and Controlling Format

This section shows how to control format and how to create insertion operators for your own classes. The insertion (<<) operator, which is preprogrammed for all standard C++ data types, sends bytes to an output stream object. Insertion operators work with predefined "manipulators," which are elements that change the default format of integer arguments.

Output Width

To align output, you specify the output width for each item by placing the setw manipulator in the stream or by calling the width member function. This example right aligns the values in a column at least 10 characters wide:

#include <iostream.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   for( int i = 0; i < 4; i++ )
   {
      cout.width(10);
      cout << values[i] << '\n';
   }
}

The output looks like this:

      1.23
     35.36
     653.7
   4358.24

Leading blanks are added to any value fewer than 10 characters wide.

To pad a field, use the fill member function, which sets the value of the padding character for fields that have a specified width. The default is a blank. To pad the column of numbers with asterisks, modify the previous for loop as follows:

for( int i = 0; i < 4; i++ )
{
   cout.width( 10 );
   cout.fill( '*' );
   cout << values[i] << endl
}

The endl manipulator replaces the newline character ('\n'). The output looks like this:

******1.23
*****35.36
*****653.7
***4358.24

To specify widths for data elements in the same line, use the setw manipulator:

#include <iostream.h>
#include <iomanip.h>

void main()
{
   double values[] = { 1.23, 35.36, 653.7, 4358.24 };
   char *names[] = { "Zoot", "Jimmy", "Al", "Stan" };
   for( int i = 0; i < 4; i++ )
      cout << setw( 6 )  << names[i]
           << setw( 10 ) << values[i] << endl;
}

The width member function is declared in IOSTREAM.H. If you use setw or any other manipulator with arguments, you must include IOMANIP.H. In the output, strings are printed in a field of width 6 and integers in a field of width 10:

 Zoot       1.23
Jimmy      35.36
   Al      653.7
 Stan    4358.24

Neither setw nor width truncates values. If formatted output exceeds the width, the entire value prints, subject to the stream’s precision setting. Both setw and width affect the following field only. Field width reverts to its default behavior (the necessary width) after one field has been printed. However, the other stream format options remain in effect until changed.

Alignment

Output streams default to right-aligned text. To left align the names in the previous example and right align the numbers, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )  << names[i]
        << resetiosflags( ios::left )
        << setw( 10 ) << values[i] << endl;

The output looks like this:

Zoot        1.23
Jimmy      35.36
Al         653.7
Stan     4358.24

The left-align flag is set by using the setiosflags manipulator with the ios::left enumerator. This enumerator is defined in the ios class, so its reference must include the ios:: prefix. The resetiosflags manipulator turns off the left-align flag. Unlike width and setw, the effect of setiosflags and resetiosflags is permanent.

Precision

The default value for floating-point precision is six. For example, the number 3466.9768 prints as 3466.98. To change the way this value prints, use the setprecision manipulator. The manipulator has two flags, ios::fixed and ios::scientific. If ios::fixed is set, the number prints as 3466.976800. If ios::scientific is set, it prints as 3.4669773+003.

To display the floating-point numbers shown in Alignment with one significant digit, replace the for loop as follows:

for ( int i = 0; i < 4; i++ )
   cout << setiosflags( ios::left )
        << setw( 6 )  
        << names[i]
        << resetiosflags( ios::left )
        << setw( 10 ) 
        << setprecision( 1 )
        << values[i] 
        << endl;

The program prints this list:

Zoot          1
Jimmy     4e+001
Al        7e+002
Stan      4e+003

To eliminate scientific notation, insert this statement before the for loop:

cout << setiosflags( ios::fixed );

With fixed notation, the program prints with one digit after the decimal point.

Zoot         1.2
Jimmy       35.4
Al         653.7
Stan      4358.2

If you change the ios::fixed flag to ios::scientific, the program prints this:

Zoot    1.2e+000
Jimmy   3.5e+001
Al      6.5e+002
Stan    4.4e+003

Again, the program prints one digit after the decimal point. If either ios::fixed or ios::scientific is set, the precision value determines the number of digits after the decimal point. If neither flag is set, the precision value determines the total number of significant digits. The resetiosflags manipulator clears these flags.

Radix

The dec, oct, and hex manipulators set the default radix for input and output. For example, if you insert the hex manipulator into the output stream, the object correctly translates the internal data representation of integers into a hexadecimal output format. The numbers are displayed with digits a through f in lowercase if the ios::uppercase flag is clear (the default); otherwise, they are displayed in uppercase. The default radix is dec (decimal).