4.2 Predefined Functions

C++ comes with libraries of predefined functions that you can use in your programs. Before we show you how to define functions, we will first show you how to use some functions that are already defined for you.

Using Predefined Functions

We will use the sqrt function to illustrate how you use predefined functions. The sqrt function calculates the square root of a number. (The square root of a number is the number that, when multiplied by itself, will produce the number you started out with. For example, the square root of 9 is 3 because 32 is equal to 9.) The function sqrt starts with a number, such as 9.0, and computes its square root, in this case 3.0. The value the function starts out with is called its argument. The value it computes is called the value returned. Some functions may have more than one argument, but no function has more than one value returned. If you think of the function as being similar to a small program, then the arguments are analogous to the input and the value returned is analogous to the output.

The syntax for using functions in your program is simple. To set a variable named theRoot equal to the square root of 9.0, you can use the following assignment statement:

theRoot = sqrt(9.0);

The expression sqrt(9.0) is called a function call (or if you want to be fancy you can also call it a function invocation). An argument in a function call can be a constant, such as 9.0, or a variable, or a more complicated expression. A function call is an expression that can be used like any other expression. You can use a function call wherever it is legal to use an expression of the type specified for the value returned by the function. For example, the value returned by sqrt is of type double. Thus, the following is legal (although perhaps stingy):

bonus = sqrt(sales)/10;

sales and bonus are variables that would normally be of type double. The function call sqrt(sales) is a single item, just as if it were enclosed in parentheses. Thus, this assignment statement is equivalent to

bonus = (sqrt(sales))/10;

You can also use a function call directly in a cout statement, as in the following:

cout << "The side of a square with area " << area
     << " is " << sqrt(area);

Display 4.1 contains a complete program that uses the predefined function sqrt. The program computes the size of the largest square dog house that can be built for the amount of money the user is willing to spend. The program asks the user for an amount of money and then determines how many square feet of floor space can be purchased for that amount of money. That calculation yields an area in square feet for the floor area of the dog house. The function sqrt yields the length of one side of the dog house floor.

Display 4.1 A Function Call

 1    //Computes the size of a dog house that can be purchased
 2    //given the user's budget.
 3    #include <iostream>
 4    #include <cmath>
 5    using namespace std;
 6
 7    int main( )
 8    {
 9        const double COST_PER_SQ_FT = 10.50;
10        double budget, area, length_side;
11
12         cout << "Enter the amount budgeted for your dog house $";
13        cin >> budget;
14
15        area = budget / COST_PER_SQ_FT;
16        length_side = sqrt(area);
17
18        cout.setf(ios::fixed);
19        cout.setf(ios::showpoint);
20        cout.precision(2);
21        cout << "For a price of $" << budget << endl
22             << "I can build you a luxurious square dog house\n"
23             << "that is " << length_side
24             << " feet on each side.\n";
25
26        return 0;
27    }

Sample Dialogue

Enter the amount budgeted for your dog house: $25.00
For a price of $25.00
I can build you a luxurious square dog house 
that is 1.54 feet on each side.

Notice that there is another new element in the program in Display 4.1:

#include <cmath>

That line looks very much like the line

#include <iostream>

and, in fact, these two lines are the same sort of thing. As we noted in Chapter 2, such lines are called include directives. The name inside the angular brackets <> is the name of a file known as a header file. A header file for a library provides the compiler with certain basic information about the library, and an include directive delivers this information to the compiler. This enables the linker to find object code for the functions in the library so that it can correctly link the library to your program. For example, the library iostream contains the definitions of cin and cout, and the header file for the iostream library is called iostream. The math library contains the definition of the function sqrt and a number of other mathematical functions, and the header file for this library is cmath. If your program uses a predefined function from some library, then it must contain a directive that names the header file for that library, such as the following:

#include <cmath>

Be sure to follow the syntax illustrated in our examples. Do not forget the symbols < and >; they are the same symbols as the less-than and greater-than symbols. There should be no space between the < and the filename, nor between the filename and the >. Also, some compilers require that directives have no spaces around the #, so it is always safest to place the # at the very start of the line and not to put any space between the # and the word include. These #include directives are normally placed at the beginning of the file containing your program.

As we noted before, the directive

#include <iostream>

requires that you also use the following using directive:

using namespace std;

This is because the definitions of names like cin and cout, which are given in iostream, define those names to be part of the std namespace. This is true of most standard libraries. If you have an include directive for a standard library such as

#include <cmath>

then you probably need the using directive:

using namespace std;

There is no need to use multiple copies of this using directive when you have multiple include directives.

Usually, all you need to do to use a library is to place an include directive and a using directive for that library in the file with your program. If things work with just the include directive and the using directive, you need not worry about doing anything else. However, for some libraries on some systems, you may need to give additional instructions to the compiler or to explicitly run a linker program to link in the library. Early C and C++ compilers did not automatically search all libraries for linking. The details vary from one system to another, so you will have to check your manual or a local expert to see exactly what is necessary.

Some people will tell you that include directives are not processed by the compiler, but are processed by a preprocessor. They’re right, but the difference is more of a word game than anything that need concern you. On almost all compilers the preprocessor is called automatically when you compile your program.

A few predefined functions are described in Display 4.2; more predefined functions are described in Appendix 4. Notice that the absolute value functions abs and labs are in the library with header file cstdlib, so any program that uses either of these functions must contain the following directive:

#include <cstdlib>

All the other functions listed are in the library with header file cmath, just like sqrt.

Display 4.2 Some Predefined Functions

Name Description Type of Arguments Type of Value Returned Example Value Library Header
sqrt square root double double sqrt(4.0) 2.0 cmath
pow powers double double pow(2.0,3.0) 8.0 cmath
abs absolute value for int int int

abs(−7)

abs(7)

7

7

cstdlib
labs absolute value for long long long

labs(−70000)

labs(70000)

70000

70000

cstdlib
fabs absolute value for double double double

fabs(−7.5)

fabs(7.5)

7.5

7.5

cmath
ceil ceiling (round up) double double

ceil(3.2)

ceil(3.9)

4.0

4.0

cmath
floor floor (round down) double double

floor(3.2)

floor(3.9)

3.0

3.0

cmath
srand Seed random number generator none none srand() none cstdlib
rand Random number none int rand() 0-RAND _MAX cstdlib

Also notice that there are three absolute value functions. If you want to produce the absolute value of a number of type int, you use abs; if you want to produce the absolute value of a number of type long, you use labs; and if you want to produce the absolute value of a number of type double, you use fabs. To complicate things even more, abs and labs are in the library with header file cstdlib, while fabs is in the library with header file cmath. fabs is an abbreviation for floating-point absolute value. Recall that numbers with a fraction after the decimal point, such as numbers of type double, are often called floating-point numbers.

Another example of a predefined function is pow, which is in the library with header file cmath. The function pow can be used to do exponentiation in C++. For example, if you want to set a variable result equal to xy, you can use the following:

result = pow(x, y);

Hence, the following three lines of program code will output the number 9.0 to the screen, because (3.0)2.0 is 9.0:

double  result, x = 3.0, y = 2.0;
result = pow(x, y);
cout << result;

Notice that the above call to pow returns 9.0, not 9. The function pow always returns a value of type double, not of type int. Also notice that the function pow requires two arguments. A function can have any number of arguments. Moreover, every argument position has a specified type and the argument used in a function call should be of that type. In many cases, if you use an argument of the wrong type, then some automatic type conversion will be done for you by C++. However, the results may not be what you intended. When you call a function, you should use arguments of the type specified for that function. One exception to this caution is the automatic conversion of arguments from type int to type double. In many situations, including calls to the function pow, you can safely use an argument of type int when an argument of type double is specified.

Many implementations of pow have a restriction on what arguments can be used. In these implementations, if the first argument to pow is negative, then the second argument must be a whole number. Since you probably have enough other things to worry about when learning to program, it might be easiest and safest to use pow only when the first argument is nonnegative.

Random Number Generation

Games and simulation programs often require the generation of random numbers. C++ has a predefined function to generate pseudorandom numbers. A pseudorandom number is one that appears to be random but is really determined by a predictable formula. For example, here is the formula for a very simple pseudorandom number generator that specifies the ith random number Ri based on the previously generated random number Ri-1:

Ri = (Ri−1 × 7) % 11

Let’s set the initial “seed,” R0 = 1. The first time we fetch a “random” number we compute R1 with the formula:

R1 = (R0 × 7) % 11 = (1 × 7) % 11 = 7 % 11 = 7

The second time we fetch a “random” number we compute R2 with:

R2 = (R1 × 7) % 11 = (7 × 7) % 11 = 49 % 11 = 5

The third time we fetch a “random” number we compute R3 with:

R3 = (R2 × 7) % 11 = (5 × 7) % 11 = 35 % 11 = 2

and so on.

As you can see, each successive value seems random unless we know the formula. This is why they are called pseudorandom. This particular function would not be a very good pseudorandom number generator because it would repeat numbers rather quickly. The random number generator in C++ varies depending upon the library implementation but uses the same basic idea as our simple generator with some enhancements to achieve a random uniform distribution.

We can get a different sequence of random numbers if we start with a different seed value. In the example, the seed always started at 1. However, if the seed is initialized with a number that changes, such as the time on the computer’s clock, then we will likely get a different sequence of random numbers every time we run the program.

To seed C++’s random number generator use the predefined method srand. It returns no value and takes as input an unsigned integer that is the initial seed value. To always seed the random number generator with the value 35, we would use:

srand(35);

To vary the random number sequence every time the program is executed, we can seed the random number generator with the time of day. Invoking the predefined function time(0) returns the number of seconds that have elapsed since January 1, 19701 on most systems. The time function requires you to include the ctime library.

#include <cstdlib>
#include <ctime>
...
srand(time(0));

We can get a random number by calling the function rand, which will return an integer in the range 0 to RAND_MAX. RAND_MAX is a constant defined in cstdlib and is guaranteed to be 32767 or higher. Usually, a number between 0 and RAND_MAX is not what is desired, in which case the random number can be scaled by modulus and addition. For example, to simulate rolling a six-sided die we could use the following:

int die = (rand() % 6) + 1;

The random number modulo 6 gives us a number between 0 and 5. Adding 1 results in a random integer that is in the range from 1 to 6.

It is important to seed the random number generator only once. A common error is to invoke srand every time a random number is generated. If both srand and rand are placed in a loop, then the likely result is a sequence of identical numbers, because the computer runs quickly enough that the time value will probably not change for repeated calls to srand.

Type Casting

Recall that 9/2 is integer division and evaluates to 4, not 4.5. If you want division to produce an answer of type double (that is, including the fractional part after the decimal point), then at least one of the two numbers in the division must be of type double. For example, 9/2.0 evaluates to 4.5. If one of the two numbers is given as a constant, you can simply add a decimal point and a zero to one (or both) numbers, and the division will then produce a value that includes the digits after the decimal point.

But what if both of the operands in a division are variables, as in the following?

int totalCandy, numberOfPeople;
 double candyPerPerson;
<The program somehow sets the value of totalCandy to 9
    and the value of numberOfPeople to 2.
    It does not matter how the program does this.>
candyPerPerson = totalCandy/numberOfPeople;

Unless you convert the value in one of the variables totalCandy or number OfPeople to a value of type double, then the result of the division will be 4, not 4.5 as it should be. The fact that the variable candyPerPerson is of type double does not help. The value of 4 obtained by division will be converted to a value of type double before it is stored in the variable candyPerPerson, but that will be too late. The 4 will be converted to 4.0 and the final value of candyPerPerson will be 4.0, not 4.5. If one of the quantities in the division were a constant, you could add a decimal point and a zero to convert the constant to type double, but in this case both quantities are variables. Fortunately, there is a way to convert from type int to type double that you can use with either a constant or a variable.

In C++ you can tell the computer to convert a value of type int to a value of type double. The way that you write “Convert the value 9 to a value of type double” is

static_cast<double>(9)

The notation static_cast<double> is a kind of predefined function that converts a value of some other type, such as 9, to a value of type double, in this case 9.0. An expression such as static_cast<double>(9) is called a type cast. You can use a variable or other expression in place of the 9. You can use other type names besides double to obtain a type cast to some type other than double, but we will postpone that topic until later.

For example, in the following we use a type cast to change the type of 9 from int to double and so the value of answer is set to 4.5:

double answer;
    answer =  static_cast<double>(9)/2;

Type casting applied to a constant, such as 9, can make your code easier to read, since it makes your intended meaning clearer. But type casting applied to constants of type int does not give you any additional power. You can use 9.0 instead of static_cast<double>(9) when you want to convert 9 to a value of type double. However, if the division involves only variables, then type casting may be your only sensible alternative. Using type casting, we can rewrite our earlier example so that the variable candyPerPerson receives the correct value of 4.5, instead of 4.0; in order to do this, the only change we need is the replacement of totalCandy with static_cast<double>(total Candy), as shown in what follows:

int totalCandy, numberOfPeople;
 double candyPerPerson;
<The program somehow sets the value of totalCandy to 9
    and the value of numberOfPeople to 2.
    It does not matter how the program does this.>
candyPerPerson =
     static_cast<double>(totalCandy)/numberOfPeople;

Notice the placement of parentheses in the type casting used in the code. You want to do the type casting before the division so that the division operator is working on a value of type double. If you wait until after the division is completed, then the digits after the decimal point are already lost. If you mistakenly use the following for the last line of the previous code, then the value of candyPerPerson will be 4.0, not 4.5.

candyPerPerson =
 static_cast<double>(totalCandy/numberOfPeople); //WRONG!

Older Form of Type Casting

The use of static_cast<double>, as we discussed in the previous section, is the preferred way to perform a type cast. However, older versions of C++ used a different notation for type casting. This older notation simply uses the type name as if it were a function name, so double(9) returns 9.0. Thus, if candyPerPerson is a variable of type double, and if both totalCandy and numberOfPeople are variables of type int, then the following two assignment statements are equivalent:

candyPerPerson =
     static_cast<double>(totalCandy)/numberOfPeople;

and

candyPerPerson =
     double(totalCandy)/numberOfPeople;

Although static_cast<double>(totalCandy) and double(totalCandy) are more or less equivalent, you should use the static_cast<double> form, since the form double(totalCandy) may be discontinued in later versions of C++.

Self-Test Exercises

  1. Determine the value of each of the following arithmetic expressions:

    sqrt(16.0) sqrt(16) pow(2.0, 3.0)
    pow(2, 3) pow(2.0, 3) pow(1.1, 2)
    abs(3) abs(−3) abs(0)
    fabs(−3.0) fabs(−3.5) fabs(3.5)
    ceil(5.1) ceil(5.8) floor(5.1)
    floor(5.8) pow(3.0, 2)/2.0 pow(3.0, 2)/2
    7/abs(−2) (7 + sqrt(4.0))/3.0 sqrt(pow(3, 2))

  2. Convert each of the following mathematical expressions to a C++ arithmetic expression:

    x+y x y+7 area+fudge
    time+tide nobody b+ b 2 4ac 2a | xy |
  3. Write a complete C++ program to compute and output the square root of PI; PI is approximately 3.14159. The const double PI is predefined in cmath. You are encouraged to use this predefined constant.

  4. Write and compile short programs to test the following issues:

    1. Determine whether your compiler will allow the #include <iostream> anywhere on the line, or if the # needs to be flush with the left margin.

    2. Determine whether your compiler will allow space between the # and the include.