You are on page 1of 36

Chapter VI

Data Type Operations

Chapter VI Topics
6.1 Introduction

6.2 Integer Operations

6.3 C++ Shortcut Notations

6.4 Real Number Operations

6.5 Mathematical Precedence

6.6 Character Operations

6.7 String Concatenation

6.8 Type Casting

6.9 Integer Overflow Problems

6.10 Real Number Precision

6.11 C++ Data Types

6.1 Introduction

Chapter VI Data Type Operations 6.1


Programming languages have special reserved words to perform certain tasks.
You saw several examples of that in the previous chapter. You also were
introduced to a variety of tools to perform specialized jobs that are stored in
function libraries. This chapter will introduce another set of tools available in
most programming languages that control operations on data types.

The majority of data operations simulate mathematical operations like addition,


subtraction, multiplication, etc. Some operations use the exact same symbols as
the ones used in mathematics and other operations have a unique set of symbols
that are strictly used by C++. You will also see that not all operations are
mathematical in nature.

This chapter is very critical because the logical correctness of a computer program
assumes correct usage of operations. C++ has a very large variety of operations
that will seem confusing at first. A lot of the confusion is not due to complexity
but to quantity. A large quantity of anything, no matter how simple, can be quite
overwhelming. Be methodical; make sure that you understand each operation,
and practice every new feature until it makes sense.

This chapter will provide detailed explanations, when detailed explanations are
considered necessary. For many situations the best explanation is a program
example that demonstrates how to use certain programming features.

6.2 Integer Operations

The addition, subtraction and division symbols of C++ are identical to


conventional mathematics symbols with the same meaning. The operation
symbol for multiplication is slightly different. Program PROG0601.CPP
demonstrates the five integer binary operations.

// PROG0601.CPP
// This program demonstrates integer operations.

Chapter VI Data Type Operations 6.2


#include <iostream.h>
#include <conio.h>

void main()
{
int Nr1 = 100;
int Nr2 = 30;
int Result1, Result2, Result3, Result4, Result5;

Result1 = Nr1 + Nr2;


Result2 = Nr1 - Nr2;
Result3 = Nr1 * Nr2;
Result4 = Nr1 / Nr2;
Result5 = Nr1 % Nr2;

clrscr();
cout << Nr1 << " + " << Nr2 << " = " << Result1
<< endl;
cout << Nr1 << " - " << Nr2 << " = " << Result2
<< endl;
cout << Nr1 << " * " << Nr2 << " = " << Result3
<< endl;
cout << Nr1 << " / " << Nr2 << " = " << Result4
<< endl;
cout << Nr1 << " % " << Nr2 << " = " << Result5
<< endl;

getch();
}

PROG0601.CPP OUTPUT

100 + 30 = 130 // Addition


100 - 30 = 70 // Subtraction
100 * 30 = 3000 // Multiplication
100 / 30 = 3 // Integer division
100 % 30 = 10 // Modulus or remainder
division

There is little explanation needed for addition, subtraction and multiplication.


Your biggest concern is that you need to remember to use an asterisk * for
multiplication.

Chapter VI Data Type Operations 6.3


Division can be a little confusing. C++ recognizes two types of division: integer
division and modulus or remainder division. Look at the examples on the next
page to understand the difference between the two types of division.

Chapter VI Data Type Operations 6.4


Integer Division Examples

12 / 3 = 4
12 / 4 = 3
12 / 5 = 2
12 / 8 = 1
12 / 12 = 1
12 / 15 = 0

There are no fractions with integer division.

Modulus (remainder) Division Examples

12 % 3 = 0
12 % 4 = 0
12 % 5 = 2
12 % 8 = 4
12 % 12 = 0
12 % 15 = 12

C++ does not always use the world’s best set of symbols.
There is no typo here. The percent (%) symbol is used for
modulus division.

6.3 C++ Shortcut Notations

The people who originally invented C++ must have had a serious phobia to
touching the keyboard. They created every conceivable shortcut notation to
shorten the source code. In the process, the code is not always very readable.
However, there are some neat shortcuts you will enjoy using, and you also need to

Chapter VI Data Type Operations 6.5


be aware of shortcut styles that are very ambiguous, and should not be used at all
for any of your program assignments. Program PROG0602.CPP gets the ball
rolling by showing the popular C++ incrementers and decrementers. You may
notice some connection here with the name of the programming language.

// PROG0602.CPP
// This program demonstrates incrementers and
decrementers.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int Nr1 = 100;
int Nr2 = 30;
cout << "Nr1 = " << Nr1 << endl;
cout << "Nr2 = " << Nr2 << endl;

Nr1++; // postfix incrementer


++Nr2; // prefix incrementer
cout << "Nr1 = " << Nr1 << endl;
cout << "Nr2 = " << Nr2 << endl;

Nr1--; // postfix decrementer


--Nr2; // prefix decrementer
cout << "Nr1 = " << Nr1 << endl;
cout << "Nr2 = " << Nr2 << endl;

getch();
}

PROG0602.CPP OUTPUT

Nr1 = 100
Nr2 = 30
Nr1 = 101
Nr2 = 31
Nr1 = 100
Nr2 = 30

Chapter VI Data Type Operations 6.6


Incrementer and Decrementer Shortcuts

K++ is a shortcut for K = K + 1;


++K is a shortcut for K = K + 1;

K-- is a shortcut for K = K - 1;


--K is a shortcut for K = K - 1;

You may be confused about the postfix and prefix notation. Like ..... where is
the difference? In the manner that the example program is written, and the
examples shown above, there is no difference. There does exist a reason for two
versions of incrementing and decrementing. The next program example will more
clearly demonstrate that a difference does exist.

// PROG0603.CPP
// This program demonstrates the difference between
// the X++ and ++X incrementers.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int X1,X2;
X1 = X2 = 10;
cout << X1 << " " << X2 << endl;
cout << ++X1 << " " << X2++ << endl;
cout << X1 << " " << X2 << endl;
getch();
}

Chapter VI Data Type Operations 6.7


PROG0603.CPP OUTPUT

10 10
11 10
11 11

This output should cause a few frowns here and there. Let us see what is
happening? First, the program assigns 10 simultaneously to X1 and X2 with the
statement X1 = X2 = 10. This is followed by displaying the values of the two
variables. The output shows an identical 10 for each variable, and you probably
expected that. Now it becomes weird. In the next output the prefix notation ++X
outputs 11 and the postfix notation outputs 10. And then with the third statement,
both variables display the value 11. What is happening here?

The difference occurs because the program combines the cout output function
with the incrementers. The prefix (++X1) has precedence over the output
function, increments first, and then displays the values. The postfix (X++)
operation does not have precedence over the output function. The output of X is
done first - with the previous X value - and then incremented.

This business of what comes first allows some real clever programming tricks. It
also creates some exceptionally ambiguous programming code. We will return to
this topic shortly and you will see that this prefix and postfix business can be
quite confusing, but luckily it can also be totally avoided.

There exists some other neat shortcuts that can be used with each of one the five
arithmetic operations. These are popular programming shortcuts that are
commonly used in C++ programs. The “no shortcut notation” you see below is a
style used by a variety of other programming languages. Program
PROG0604.CPP shows the details of each one of the shortcuts, on the next page.

Basic Operations Shortcuts

No Shortcut Notation Shortcut Notation

K = K + 5 K += 5
K = K - 5 K -= 5
K = K * 5 K *= 5

Chapter VI Data Type Operations 6.8


K = K / 5 K /= 5
K = K % 5 K %= 5

The "no shortcut" notation is a very legitimate programming


style. In C++ you will find this style rarely used. In the
majority of programs you will notice the "shortcut" notation
to be the popular choice.

// PROG0604.CPP
// This program demonstrates using shortcut notation
with
// each one of the 5 basic operations.

#include <iostream.h> // Necessary for program


input/output
#include <conio.h> // Necessary for Console
operations, like clrscr

void main()
{
clrscr();
int Nr = 100;
cout << "Nr " << Nr << endl << endl;

Nr += 10;
cout << "Nr += 10 " << Nr << endl << endl;

Nr -= 20;
cout << "Nr -= 20 " << Nr << endl << endl;

Nr *= 2;
cout << "Nr *= 2 " << Nr << endl << endl;

Nr /= 5;
cout << "Nr /= 5 " << Nr << endl << endl;

Nr %= 7;
cout << "Nr %= 7 " << Nr << endl << endl;

getch();
}

Chapter VI Data Type Operations 6.9


PROG0604.CPP OUTPUT

Nr 100

Nr += 10 110

Nr -= 20 90

Nr *= 2 180

Nr /= 5 36

Nr %= 7 1

The Danger of Combining Shortcuts

Using a shortcut like K++ is neat, and it is also pretty nice to use shortcuts like
K+=5 and K/=L. The problem starts when over-enthusiastic C++ programmers
go overboard on the shortcut business. They frequently combine too many
statements together with some very difficult-to-predict results. I will show you
two programs that demonstrate this point. The first program is not too bad, and
most people can determine the output. The second program is pretty bizarre and
should convince anybody about the problems with shortcuts.

// PROG0605.CPP
// This program demonstrates complexity caused
// by combining incrementers.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int X = 10;
++X += X++;
cout << "X = " << X << endl << endl;
getch();
}

Chapter VI Data Type Operations 6.10


PROG0605.CPP OUTPUT

X = 23

I have intentionally not explained how this program works. Many teachers will
prefer if students are simply told not to combine shortcuts. Any explanation and
increased knowledge in the area of shortcuts may increase the likelihood of
students using undesirable shortcuts.

Who needs an explanation? Perhaps you understand where the value 23 comes
from. If you do, you will enjoy program PROG0606.CPP. This program is
quite challenging and hopefully convinces everybody that this shortcut business
can get pretty crazy in a hurry.

The output of the next program example is intentionally not shown. It is more
interesting to see how many students can determine what the output will be. The
point about using too many shortcuts is more convincing when the majority of
students do not compute the correct answer. On the other hand, if you already
knew the answer from the chapter reading, it becomes difficult to determine what
you remembered from reading and what you determined on your own.

Check PROG0606.CPP and put on your thinking cap. Can you figure out what
the output is? If you are confused, do not feel bad, because most students have
serious problems with this style of code.
// PROG0606.CPP
// This program shows complexity with combining
incrementers.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int X = 10;
++X += (X++ + ++X);
cout << "X = " << X << endl << endl;
getch();
}

PROG0606.CPP OUTPUT

Chapter VI Data Type Operations 6.11


The output is intentionally not shown.

Did you figure the output correctly? Right. Well, whether you understood the
output of the previous program or not, remember the following warning.

C++ Shortcut Warning

C++ shortcut operations should not be combined with any


other type of operation or any other type of statement.

The results of many combinations is non-standard. It can


fluctuate with different compilers and results are unpredictable.

Proper Usage:

K++;
cout << K << endl;

Problematic Usage:

cout << K++ << endl;

6.4 Real Number Operations

Real number operations closely resemble the operations with integers. The only
difference in the operations is with division. Real numbers do not have integer
division or remainder division. You do have division that computes a fractional
answer. The C++ data type, used earlier for real numbers is float, short for
floating point number. Program PROG0607.CPP demonstrates real operations.

// PROG0607.CPP
// This program demonstrates real number operations
// implemented with the float type.

Chapter VI Data Type Operations 6.12


#include <iostream.h>
#include <conio.h>

void main()
{
float Nr1 = 1000;
float Nr2 = 3.3;
float Result1, Result2, Result3, Result4;
Result1 = Nr1 + Nr2;
Result2 = Nr1 - Nr2;
Result3 = Nr1 * Nr2;
Result4 = Nr1 / Nr2;
clrscr();
cout << Nr1 << " + " << Nr2 << " = " << Result1
<< endl;
cout << Nr1 << " - " << Nr2 << " = " << Result2
<< endl;
cout << Nr1 << " * " << Nr2 << " = " << Result3
<< endl;
cout << Nr1 << " / " << Nr2 << " = " << Result4
<< endl;
getch();
}

PROG0607.CPP OUTPUT

1000 + 3.3 = 1003.299988


1000 - 3.3 = 996.700012
1000 * 3.3 = 3300
1000 / 3.3 = 303.030304

The output shows some expected fractional digits beyond the decimal (floating)
point. On the other hand, output like 1003.299988 does not inspire confidence.
Should that output not be in the neighborhood of 1003.3? You are right, and for
this reason real numbers in C++ normally use the double type, not the float type.
At the end of this chapter, we will investigate computer precision very closely,
and provide more information about the differences between the many data types
available in C++.
// PROG0608.CPP
// This program demonstrates real number operations
// implemented with the double type.

#include <iostream.h>
#include <conio.h>

Chapter VI Data Type Operations 6.13


void main()
{
double Nr1 = 1000;
double Nr2 = 3.3;
double Result1, Result2, Result3, Result4;
Result1 = Nr1 + Nr2;
Result2 = Nr1 - Nr2;
Result3 = Nr1 * Nr2;
Result4 = Nr1 / Nr2;
clrscr();
cout << Nr1 << " + " << Nr2 << " = " << Result1
<< endl;
cout << Nr1 << " - " << Nr2 << " = " << Result2
<< endl;
cout << Nr1 << " * " << Nr2 << " = " << Result3
<< endl;
cout << Nr1 << " / " << Nr2 << " = " << Result4
<< endl;
getch();
}

PROG0608.CPP OUTPUT

1000 + 3.3 = 1003.3


1000 - 3.3 = 996.7
1000 * 3.3 = 3300
1000 / 3.3 = 303.030303

The output of program PROG0608.CPP shows the type of result that you had
probably expected. All the future program examples, which use real numbers,
will use the double real number type.

6.5 Mathematical Precedence

Chapter VI Data Type Operations 6.14


C++ may not use all the exact same symbols for mathematical operations, but the
precedence of operations is totally identical. Rules like multiplication/division
before addition/subtraction and parenthesis before anything else apply in C++.
Parenthesis are also used in the same manner as they are in mathematics. You do
need to be careful that operators are always used. In mathematics, operators are
frequently assumed, but not used. This is especially true for the multiplication
operator. A small chart below helps to clarify this point.

Be Aware of Hidden Operators in Mathematics

Mathematics C++ Source Code

5XY 5*X*Y

4X + 3Y 4*X + 3*Y

6(A - B) 6*(A - B)

5 5/7
7

A + B (A + B)/(A - B)
A - B

AB (A * B)/(X * Y)
XY

Mathematical precedence usually is not a problem for students. However, leaving


out operators or parentheses, which are not required in regular mathematical
expressions, is a common problem for beginning computer science students.

Program PROG0609.CPP demonstrates a variety of expressions that use


mathematical precedence. You will also need to realize that mathematical
accuracy is not always the same as computer accuracy. You saw earlier that the
double type stored numbers more accurately than the float type. Numerical
values are stored in memory and memory is frequently limited on purpose or
accidentally. Either way, it is common that some mathematical accuracy may get
sacrificed to save memory. On the other hand, this may precisely be the reason

Chapter VI Data Type Operations 6.15


why you should be using a different data type. We will return to this topic some
more. For now plant a seed in your head.

// PROG0609.CPP
// This program demonstrates math precedence in C++.

#include <iostream.h>
#include <conio.h>

void main()
{
double A,B,C, Result;
A = 1000;
B = 100;
C = 2.5;

clrscr();
cout << "A = " << A << " B = " << B << " C = "
<< C << endl << endl;
Result = A + B * C;
cout << "A + B * C = " << Result << endl;
Result = (A + B) * C;
cout << "(A + B) * C = " << Result << endl;
Result = A / B * C;
cout << "A / B * C = " << Result << endl;
Result = A * B / C;
cout << "A * B / C = " << Result << endl;

getch();
}

PROG0609.CPP OUTPUT

A = 1000 B = 100 C = 2.5

A + B * C = 1250
(A + B) * C = 2750
A / B * C = 25
A * B / C = 40000

Chapter VI Data Type Operations 6.16


6.6 Character Operations

The title of this section may surprise you. Performing operations with integers
and real numbers makes good sense to you. Doing operations with characters is
quite another story. Relax, we will not add A + B and somehow get C, but we
will do similar operations and you need to be aware of the manner in which C++
deals with character data types.
It is very important to understand that characters are stored, and treated, like
numerical values by C++. One byte of memory is used for characters, and this
allows 256 different combinations for 256 different characters. When you use
mathematical operators with characters, results are determined based on the
computation of the numerical values of the characters. The next example,
program PROG0610.CPP demonstrates addition and subtraction with characters.

// PROG0610.cpp
// This program demonstrates that characters
// are stored as numbers.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
cout << "'a' - 'A' = " << 'a' - 'A' << endl;
cout << "'b' - 'B' = " << 'b' - 'B' << endl;
cout << "'z' - 'Z' = " << 'z' - 'Z' << endl;
cout << "'a' + 'A' = " << 'a' + 'A' << endl;
cout << "'b' + 'B' = " << 'b' + 'B' << endl;
cout << "'z' + 'Z' = " << 'z' + 'Z' << endl;
getch();
}

PROG0610.CPP

'a' - 'A' = 32
'b' - 'B' = 32
'c' - 'C' = 32
'a' + 'A' = 162
'b' + 'B' = 164
'c' + 'C' = 212

Chapter VI Data Type Operations 6.17


The previous program intentionally subtracted several upper-case letters from
lower-case letters. It showed the relationship between the two types of letters.
With ASCII characters you will find that the difference between all the upper-
case letter values and lower-case letter values is 32.

The previous program showed addition and subtraction of characters only. The
next program example will demonstrate what happens when you try to add
numbers to characters. It will also show the incrementer operation used with a
character variable.

// PROG0611.cpp
// This program demonstrates operations with character
variables.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
char Char1, Char2;
Char1 = 'A';
Char2 = Char1 + 5;
cout << Char1 << " + 5 = " << Char2 << endl;

Char2 = Char1 + 10;


cout << Char1 << " + 10 = " << Char2 << endl;

Char1++;
cout << "Char1++ = " << Char1 << endl;

getch();
}

PROG0611.CPP OUTPUT

A + 5 = F
A + 10 = K
Char1++ = B

Chapter VI Data Type Operations 6.18


This output will require some analyzing. The result is quite logical, as long as
you remember that characters are considered numbers by C++. The character A is
stored as value 65. The operation A + 5 means then 65 + 5 = 70. The character
associated with 70 is F.

A similar logic is used with the operation A + 10, which computes 65 + 10


resulting in 75. The character associated with 75 is K. Finally, incrementing with
Char1++ results in the very next character. Char1 stores the value of A as 65.
65 is incremented to 66, and that value is associated with B.

6.7 String Concatenation

You were totally impressed that C++ managed to perform arithmetic operations
on characters. Do you believe C++ can continue its amazing performance and
also perform operations with strings? Probably a stupid question? Why would a
section be titled String Concatenation, if such an operation did not exist?

You need to realize that there will not be cute tricks like adding numerical values
that represent characters. In fact, there will not be addition in the numerical sense
at all. The + operator will be used, but it has a different meaning with strings,
and it is called concatenation.

String Concatenation

Concatenation is the appending of a second string to a


first string.

"Hello" + "World" = "HelloWorld"

"Hello" + " " + "World" = "Hello World"

"100" + "200" = "100200"

Chapter VI Data Type Operations 6.19


The plus operator ( + ) is used both for arithmetic addition
and string concatenation. The same operators performs
two totally different operations.

In computer science when an operator is used for more


than one operation, the operator is said to be overloaded.

The apstring, introduced in the last chapter, implements concatenation with the
plus + operator. You will note something here that will occur frequently in C++.
Symbols and operators will have different meanings in different situations.

// PROG0612.cpp
// This program demonstrates concatenation with
strings.

#include <iostream.h>
#include <conio.h>
#include "APSTRING.H"

void main()
{
clrscr();
apstring String1 = "Good";
apstring String2 = "Morning";
apstring String3;
String3 = String1 + ' ' + String2;
cout << String1 << " + " << String2 << " = " <<
String3
<< endl;
getch();
}

PROG0612.CPP OUTPUT

Good + Morning = Good Morning

Chapter VI Data Type Operations 6.20


There are many more operations that can be performed with apstring. These
operations will be shown in a future chapter that specializes in using function
libraries. For now, you will need to be satisfied with string assignment and string
concatenation.

6.8 Type Casting

In the last chapter, I mentioned that you need to be careful when you mix different
data type variables. You may get results that are unexpected. If you understand
what is happening, you will note that the results are not unexpected. Furthermore,
you can take control, and intentionally assign one data type to a different data
type for a desired result. Intentionally assigning one data type to another type is
called type casting.

Type Casting Definition

Type casting is the intentional assignment of one “indicated”


data type to another data type. Indication is important.

double Result;
Result = 5/3; // integer division

double Result;
Result = (double) 5/3; // real division
// due to type casting

You have already seen the unique relationship between characters and integers.
In program PROG0613.CPP you will see the character/integer relationship
repeated and see various other relationships as well.

// PROG0613.CPP

Chapter VI Data Type Operations 6.21


// This program demonstrates type casting in C++.

#include <iostream.h>
#include <conio.h>

void main()
{
char Var1;
int Var2;
float Var3;
Var1 = 'A';
Var2 = 65;
Var3 = 3.14159;

clrscr();
cout << Var1 << endl;
cout << Var2 << endl;
cout << Var3 << endl;
cout << endl;
cout << "A becomes " << (int) Var1 << endl;
cout << "65 becomes " << (char) Var2 << endl;
cout << "65/3 without casting becomes " << Var2/3 <<
endl;
cout << "65/3 with casting becomes " << (float)
Var2/3 << endl;
cout << "3.14159 becomes " << (int) Var3 << endl;

getch();
}

PROG0613.CPP and PROG0614.CPP OUTPUT

A
65
3.14159

A becomes 65
65 becomes A
65/3 without casting becomes 21
65/3 with casting becomes 21.666666
3.14159 becomes 3

Chapter VI Data Type Operations 6.22


The exact same results can be produced with a slightly different syntax style for
type casting. You may also place parenthesis around the variable of expression
that is typecasted. In such a case the parenthesis are not necessary around the data
type. This style of type casting is shown with PROG0614.CPP.

// PROG0614.CPP
// This program demonstrates a second syntax style
// for type casting.

#include <iostream.h>
#include <conio.h>

void main()
{
char Var1;
int Var2;
double Var3;

Var1 = 'A';
Var2 = 65;
Var3 = 3.14159;

clrscr();
cout << Var1 << endl;
cout << Var2 << endl;
cout << Var3 << endl;
cout << endl;
cout << "A becomes " << int (Var1) << endl;
cout << "65 becomes " << char (Var2) << endl;
cout << "65/3 without casting becomes " << Var2/3 <<
endl;
cout << "65/3 with casting becomes " << float
(Var2/3) << endl;
cout << "3.14159 becomes " << int (Var3) << endl;

getch();
}

Type casting is a powerful tool in C++. Use this tool wisely and carefully. The
compiler knows correct syntax, but the compiler does not know what is in your
head. You must be logical and determine how to use variables properly.
6.9 Integer Overflow Problems

Chapter VI Data Type Operations 6.23


Several program examples back, you noticed that a program, which used float,
performed mathematical operations that did not match mathematical accuracy. It
was your first exposure to the reality that computer reality and mathematical
reality are not always the same.

In this section we will explore the reasons for such inaccuracies. In particular,
we are going to take a close look at the problems that can very easily occur with
integers. What type of problems am I talking about? Check out program
PROG0615.CPP and notice the very odd, inaccurate, output that is shown. The
title of this chapter section is Integer Overflow Problems because mathematical
inaccuracies happen when a number overflows.

// PROG0615.CPP
// This program demonstrates integer overflow problems.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
int Number = 20000;
cout << "Number: " << Number << endl;
Number += 10000;
cout << "Number: " << Number << endl;
Number += 10000;
cout << "Number: " << Number << endl;
Number = 32767;
cout << "Number: " << Number << endl;
Number++;
cout << "Number: " << Number << endl;
getch();
}

PROG0615.CPP

Number: 20000
Number: 30000
Number: -25356
Number: 32767
Number: -32768

Chapter VI Data Type Operations 6.24


The program output quickly convinces you that there are problems with accuracy.
Number starts out with the value 20000. No problem. Now 10000 is added to
Number, which now displays 30000. Still no problem.
The next step is strange. A second 10000 is added to Number, which should give
a value of 40000. However, the computer displays -25356. Definitely a problem.

Another oddity occurs after 32767 is assigned to Number. Incrementing by 1


should yield an output of 32768. You see that output .... sort of. But the number
has become negative. To understand what is happening, we need to take a little
detour to driving a car. The odometer of a car has a maximum number of miles
that can be displayed based on the number of displayed digits. Most odometers
are 6 or 7 digits. Consider a 6 digit odometer with 99,999 miles.

0 9 9 9 9 9

This odometer cannot display a larger number with 5 digits. One more mile and
the entire display will change. Each one of the digits will change from 9 to 0, and
the 0 on the far left will become 1.

1 0 0 0 0 0

You also need to realize that the odometer will max out at 999,999. It is not
possible to display 1,000,000. The limit of the number is based on the limit of the
number of displayed digits.

The same exact logic applies to variables in a computer. Different variables are
assigned different amounts of memory. In Turbo C++ an integer is allocated 2
bytes of memory. This means a total of 16 bits are used to represent an integer in
memory. Furthermore, remember that every bit can only have two different
values: 0 or 1. As a human being you may think in base 10, but the computer is
busily storing values - and computing values - in machine code, base 2. The
largest possible 6-digit number in base 10 is 999,999 and the absolute largest
possible 16-digit number in base-2 is represented by the simulated integer
memory below.

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Chapter VI Data Type Operations 6.25


Base 2 number 1111 1111 1111 1111 = 65535 in base 10.

This does not explain why 32767 + 1 gives negative results. The largest possible
integer, depicted above is not how an int is represented in C++. Numbers can be
positive or negative and the first bit is the sign bit. That leaves 15 bits for
representing the number. The 0 in the first bit indicates a positive number. A 1 in
the first bit is for a negative number. This means that 0 followed by 15 1s is the
largest integer, which equals 32,767.

How Positive Numbers Give Negative Results

0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Now logically speaking 32767 + 1 = 32768. If we convert these same values to


base 2, we get:

0111 1111 1111 1111 + 1 = 1000 0000 0000 0000

This follows the same logic as 99,999 + 1 = 100,000. We do not see that logic
with the 32767, base 10 number, because we have not reached any maximum
digit values with base 10. At the base 10 level, 32,767 simply increments to
32,768. At the base 2 level the equivalent values “rollover” and result in the
integer value shown below.

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Note, however, that the sign-bit, which was positive, has been changed to 1 and
now the whole number is negative. This is as far as we want to look at these
negative numbers. There is more complexity to the storing and management of
negative numbers.

If you read other computer science text books, you may see something called
complement arithmetic. There is a special way to compute negative values in
base 2. Right now the biggest point to realize, and remember, is that you will
get incorrect values when the variable “overflows.” This means that you need to
be very conscious that you pick the correct data type.

Chapter VI Data Type Operations 6.26


Overflow Problems

Overflow is a situation where the assigned value of a variable


exceeds the allocated storage space.

The resulting value that is stored will be inaccurate and can


change from positive to negative or negative to positive.

Avoid overflow problems by using a data type that can


handle the size of the assigned values.

It is important to save computer memory. However, do not


be so stingy with memory that overflow problems occur.

6.10 Real Number Precision

Several sections ago, we changed from float to double for our real number data
type of choice. In this section we are going to take a closer look at real numbers
and how we can control accuracy of the real numbers that are stored. You already
know from the previous integer overflow section that too large a number in too
little space causes problems. The float data type has 4 bytes, and double reserves
8 bytes to store its variables. This is considerably more than the modest 2 bytes
allowed for an integer. However, integers are not concerned with storing
fractional amounts. There can be plenty of problems with real number precision.

The first program example, PROG0616.CPP concentrates on the float data type
and displays, or tries to display, numbers that steadily increase the number of
digits beyond the decimal point. It does not take long before float runs out off
gas and stops giving proper precision. This program helps to identify the point
where this happens.

Chapter VI Data Type Operations 6.27


// PROG0616.CPP
// This program demonstrates precision problems with
float.

#include <iostream.h>
#include <conio.h>

void main()
{
clrscr();
float Number;

Number = 9.1;
cout << "Number 9.1 = " << Number << endl;

Number = 9.12;
cout << "Number 9.12 = " << Number << endl;

Number = 9.123;
cout << "Number 9.123 = " << Number << endl;

Number = 9.1234;
cout << "Number 9.1234 = " << Number << endl;

Number = 9.12345;
cout << "Number 9.12345 = " << Number << endl;

Number = 9.123456;
cout << "Number 9.123456 = " << Number << endl;

Number = 9.1234567;
cout << "Number 9.1234567 = " << Number << endl;

Number = 9.12345678;
cout << "Number 9.12345678 = " << Number << endl;

getch();
}

PROG0616.CPP OUTPUT

Number 9.1 = 9.1


Number 9.12 = 9.12
Number 9.123 = 9.123

Chapter VI Data Type Operations 6.28


Number 9.1234 = 9.1234
Number 9.12345 = 9.12345
Number 9.123456 = 9.123456
Number 9.1234567 = 9.123457
Number 9.12345678 = 9.123457

You see in the program source code of PROG0616.CPP that the number of
digits, beyond the decimal point, increases to eight. The output shows that the
float data type throws in the towel after six digits are displayed. Does this mean
that a double real number type allows twelve digits to be displayed? A logical
question. Let us check out some of these concerns.

A float data type allocates four bytes of memory. A double data type allocates
eight bytes of memory. The doubling of the memory allocation accounts for the
naming of the double type. With twice the number of bytes, it certainly is
possible to store more information. The larger space allows storing a larger
number as well as store more precision for the fractional portion beyond the
floating point. Floating point seems more accurate than decimal point. You may
see number in the decimal, base 10, notation. The computers sees numbers in the
binary, base 2, notation. Base 2 does not have any decimal point, but it is very
accurate to use the term floating point. This also explains the name of the C++
real number data type float.

C++ allows control over the digits following the floating point. It is done with the
setprecision function. Access to this function requires including the iomanip.h
function library. It makes sense to use a special function to indicate desired
precision. C++ is basically at a loss how accurately numbers should be displayed.
Programs that involve the processing of monetary values are happy with accuracy
that only goes two places beyond the floating point. A navigation program used
for a space shuttle mission will require much greater accuracy. How about the
construction of micro chips? Placing millions of bytes in one small space requires
an accuracy that is hard to imagine.

In program PROG0617.CPP we will see if using this new function helps to


make float more precise, and we can also compare the accuracy of float and
double. The program starts by comparing float and double without any special
function calls. Halfway through the program, setprecision(15) kicks in,
specifying that real number output needs to be accurate to 15 digits beyond the
floating point.

Now it is easy enough to state that accuracy of 15 digits beyond the floating point
is required. Do you get such accuracy? In other words, what are the limitations,
if any, of the setprecision function?

Chapter VI Data Type Operations 6.29


The next program example is somewhat long and tedious. It keeps repeating the
same pattern as the previous statement. Each time, an attempt is made to display
the accuracy with a real number that has one more digit assigned, beyond the
floating point, than the previous output. This approach allows us to pinpoint the
precise location where setprecision will no longer be accurate.

// PROG0617.CPP
// This program demonstrates precision with float and
double.

#include <iostream.h>
#include <conio.h>
#include <iomanip.h> // required for setprecision
function

void main()
{
clrscr();
float FNr;
double DNr;

cout << "BEFORE USING SETPRECISION(15)" << endl;


cout << endl;
FNr = 9.123456;
cout << "Float 9.123456 = " << FNr << endl;
DNr = 9.123456;
cout << "Double 9.123456 = " << DNr << endl;
cout << endl;
FNr = 9.1234567;
cout << "Float 9.1234567 = " << FNr << endl;
DNr = 9.1234567;
cout << "Double 9.1234567 = " << DNr << endl;
cout << endl;

cout << setprecision(15);


cout << "AFTER USING SETPRECISION(15)" << endl;
cout << endl;
FNr = 9.1234567;
cout << "Float 9.1234567 = " << FNr <<
endl;
DNr = 9.1234567;
cout << "Double 9.1234567 = " << DNr <<
endl;

Chapter VI Data Type Operations 6.30


cout << endl;
FNr = 9.12345678;
cout << "Float 9.12345678 = " << FNr <<
endl;
DNr = 9.12345678;
cout << "Double 9.12345678 = " << DNr <<
endl;
DNr = 9.123456789012;
cout << "Double 9.123456789012 = " << DNr <<
endl;
DNr = 9.1234567890123;
cout << "Double 9.1234567890123 = " << DNr <<
endl;
DNr = 9.12345678901234;
cout << "Double 9.12345678901234 = " << DNr <<
endl;
DNr = 9.123456789012345;
cout << "Double 9.123456789012345 = " << DNr <<
endl;

getch();
}

PROG0617.CPP OUTPUT

BEFORE USING SETPRECISION(15)

Float 9.123456 = 9.123456


Double 9.123456 = 9.123456

Float 9.1234567 = 9.123457


Double 9.1234567 = 9.123457

AFTER USING SETPRECISION(15)

Float Number: 9.123456954956055


Double Number: 9.1234567

Chapter VI Data Type Operations 6.31


Float 9.12345678 = 9.1234569549566055
Double 9.12345678 = 9.12345678
Double 9.123456789012 = 9.123456789012
Double 9.1234567890123 = 9.1234567890123
Double 9.12345678901234 = 9.123456789012341
Double 9.123456789012345 = 9.123456789012344

An earlier program demonstrated that double performed more accurate


computations than float. With this program example you notice that double
allows twice the number of accurate digits following the floating point. However,
do keep in mind that you need to use the setprecision function to make double
manage that many digits accurately. At the same time, double also has its
limitations. You may use a statement like setprecision(30) and that is fine, but do
not expect accuracy to 30 digits.

6.11 C++ Data Types

So far only a few of the C++ data types have been discussed. It turns out that C+
+ has a wide variety of integer and real number data types that you have not seen
yet. There are integer types that are both smaller and larger than int and there are
more real numbers than just float and double. C++ has numerical data types that
take as little as 1 byte and as many as 10 bytes for memory. One feature that C+
+ allows is provided with the reserved word, unsigned. Placing this word in front
of an integer type doubles the maximum value of the integer, but limits the values
to non-negative numbers. The sign bit is no longer used and numbers can be
twice the signed value.

Program PROG0618.CPP demonstrates each one of the C++ numerical data


types. The comments in the program are also a good reference. You will note the
comment next to each data type about the memory requirement and value range.

// PROG0618.CPP
// This program demonstrates the various integer
// and real C++ data types

Chapter VI Data Type Operations 6.32


#include <iostream.h>
#include <conio.h>

void main()
{
char Int1; // 1 byte -128..127
unsigned char Int2; // 1 byte 0..255
int Int3; // 2 bytes -32768..32767
unsigned int Int4; // 2 bytes 0..65535
long Int5; // 4 bytes -
2,147,483,647..2,147,483,647
unsigned long Int6; // 4 bytes 0..4,294,967,295
float Float1; // 6 bytes 3.4e-38..3.4e38
double Float2; // 8 bytes 1.7e-308..1.7e308
long double Float3; // 10 bytes 3.4e-
4932..1.1e4932
Int1 = 127;
Int2 = 255;
Int3 = 32767;
Int4 = 65535;
Int5 = 2147483647;
Int6 = 4294967295;
Float1 = 3.4e38;
Float2 = 1.7e308;
Float3 = 1.1e4932;

clrscr();
cout << (int) Int1 << endl; // type casting is
needed
cout << (int) Int2 << endl; // type casting is
needed
cout << Int3 << endl;
cout << Int4 << endl;
cout << Int5 << endl;
cout << Int6 << endl;
cout << endl;
cout << Float1 << endl;
cout << Float2 << endl;
cout << Float3 << endl;
getch();
}

Chapter VI Data Type Operations 6.33


PROG0618.CPP OUTPUT

127
255
32767
65535
2147483647
4294967295
3.4e38
1.7e308
1.1e4932

This program showed many, many different data types. These types are shown
partially for your curiosity, and partially to create a reference if you need to use a
special data type.

APCS Examination Requirements

At regular intervals I will make reference to the APCS C++ Subset or about
requirements for the APCS Examination. APCS stands for Advanced Placement
Computer Science. C++ is a very, very large programming language. The
College Board and ETS (Educational Testing Service), the folks who create the
APCS Examination, have created a C++ Subset that will be used to test students
for college credit.

The Exposure C++ series will cover every topic of the APCS Curriculum and
every feature of the APCS C++ subset. There will also be some additional topics
that are meant to be enrichment. One example is the data type section that was
just now mentioned.

It will be helpful for students and teachers in general to observe summary boxes
that help to summarize certain computer science features. These summaries are
provided at the conclusion of various topics. I believe this is more beneficial than
a summary at the end of each chapter. You are still getting a summary of
important facts, but they are provided throughout the chapter.

Special summary boxes, titled APCS Examination Alert, will be


presented when topics of particular interest for APCS Examination candidates are
presented. It is my primary intention to present you with computer science
information. But I have a secondary intention to prepare you for the APCS
Examination. Frequently, questions come up about the inclusion of a topic on the

Chapter VI Data Type Operations 6.34


APCS Examination. Hopefully, a healthy sprinkling of these alert boxes will
assist you in clarifying examination concerns.
APCS Examination Alert

C++ has many simple (single-value) data types.

You are expected to understand and use only the


following data types:

char // (1 byte character or integer)


int // (2 byte integer)
double // (8 byte real number)
bool // (will be explained later)

For an APCS Examination, understand means that you can


handle questions that include the specified topics. This is
primarily true for the multiple choice examination.

The word use means that you can write C++ source code
that includes the specified topic.

The bool Data Type Comes Later

There exists a data type that stores either the value true or the value false. This
data type is called bool, short for Boolean. You will receive detailed information
about this data type in a later chapter.

Chapter VI Data Type Operations 6.35


C++ Warning

C++ is an industrial strength language. This language is


designed for, and used for, many industry-wide applications.

This means that C++ is expected to be used by professional


programmers who can handle the many complexities of a
major programming language.

Computer science students, new to programming, can easily


get in trouble because C++ does not provide many guards
against student peculiarities.

Student may also be using C-style programming that is


considered obsolete by modern computer science standards.
Even though C++ will compile older, C-style features, you
should not use features that have not been introduced. Please
check with your teacher about the inclusion of any program
keyword, operator or style that you are not sure about.

Frequently, there is the temptation to use some shortcut,


to use some other method because it was shown in a
magazine, presented on the Internet, or provided by a friend.
Regardless of the source, you are well advised to follow
your teacher’s guidelines closely.

Failure to follow suggestions may result in computer lock-ups


that can mean very time-consuming cold-boots.

Chapter VI Data Type Operations 6.36

You might also like