Functions from Math (brief review)

Definition:

   f(x) = 3x + 2

   g(x) = (x - 4)2

Where x is known as the independent variable, the function input, and/or the argument to the function. The functions (f and g) are defined by a simple equation.

In programming, we call x either the function's input or its formal argument (not the independent variable). Functions in programming languages are rarely defined so simply (except those of systems like Mathematica or Maple where the emphasis is on ease of use by students, teachers, etc.).

Evaluation:

   f(4) = 3*4 + 2 = 14

   g(4) = (4 - 4)2 = 0

   f(a) = 3a + 2

(Mathematica/Maple:

    a = 4
    f(a) = 3*a + 2 = 3*4 + 2 = 14)

This is known as evaluation of a function at a 'point' or at a particular value for the independent variable.

(The Mathematica/Maple example is merely saying that the variable a is assigned a value of 4 and that the function f is being evaluated at the current value of a.)

In programming, we refer to this as 'calling the function' and passing it the actual argument value. (The Mathematica/Maple example works in programming languages, too — passing a variable as an actual argument is perfectly legal.)

Composition:

                   2
f(g(4)) = 3*(4 - 4)  + 2 = 3*0 + 2 = 2

                       2           2
g(f(4)) = (3*4 + 2 - 4)  = (14 - 4)  = 100

Here we have evaluated a function at a value and then used that value as the input to the next (outer) function. (We could also solve for the actual formula of f(g(x)) in general. But we do not have to in programming, so why bother?)

In programming, this is called nesting a function call — one function call is used as the argument to the next (outer) one.

Multiple Independent Variables:

   f(x,y) = x2 + y2

   f(3,2) = 32 + 22 = 13

Here we have a function that has more than a single input. Functions with one independent variable generate curves/lines in the 2D (Cartesian) plane. Those with two independent variables generate surfaces in a 3D space. (More independent variables are possible, but are quite a bit more difficult to picture.)

Programming languages allow us to have multiple arguments to our functions, as well.

Translating Math Notation to C++

Most programming languages support pre-defined (built-in/library) functions to do many standard mathematical tasks. C++ is no different. Among the standard libraries of C++ you'll find the 'math' library. This library's interface is defined in cmath. To use functions defined in the cmath library, you must remember to place a #include for its interface at the top of your program (typically right after the one for the iostream library's interface inclusion).

Math
Symbolism
Meaning C++
Equivalent
Notes
   ___
 \/ x
take the square root of x sqrt(x) Doing only square roots, it tends to be much faster than using pow(x,0.5).
  |x|
take the absolute value of x fabs(x) Like all the cmath functions, fabs is focused on performing operations on double type data. (Also see the cstdlib functions abs and labs
  xy
raise x to the yth power pow(x,y) Note that although ^ is a C++ operator, it does not act as exponentiation or 'raise to a power' like on a calculator (or in Mathematica/Maple). Its operation is so mysterious and strange that we do not even discuss it until CSC122!

Also note that you can use the pow() function to evaluate roots other than the square root by using a fractional second actual argument/input. (You could pass 1./2 to get a square root as well, but sqrt() will evaluate faster because it has been designed to do square roots and do them well.
  ex
raise e to the xth power exp(x) And if you need to actually use the value of e itself, you'll have to call exp(1.0)! I'd suggest not doing this too often, perhaps in the creation of a constant like:

    const double MATH_E = exp(1.0);

(Can you believe that C++ failed to provide a simple constant for you. *pout*)
  ln x
take the natural logarithm of x (the logarithm to the base e) log(x) No. I'm not kidding. They changed its name to conflict with the standard math notation of the common logarithm. *shakes head in disgust and shame* I can not believe I work with these people!
  log x
take the common logarithm of x (the logarithm to the base 10) log10(x) (*sigh* *shakes head again* I still can not believe it!
  | x |
  -- --
greatest integer of x

i.e. the largest whole number that is less than or equal to x
floor(x) This is often represented in calculators as int and is located under the MATH menu on a TI-83/84. The 'math' notation is actually used in higher-level computer science. I've yet to meet a pure mathematician that knew what the notation stood for.

Note that the return value of this function is double — not any type of integer. Even though it essentially truncates the decimal places away, double has more digits of precision than even the largest integer type (~15 compared to 10). Therefore, double must be returned because the whole number part may still be too large to fit in an integer type.
  __ __
  | x |
least integer

i.e. the smallest whole number that is greater than or equal to x
ceil(x) Same note about notation here as for floor(). But there is no standard calculator equivalent.

Also same note here as for floor() with regards to the return type.
  sin x
sine of x (x is measured in radians) sin(x) Unfortunately, the standard library has failed to provide a constant for the value of π so you would not have to remember/transcribe all those digits. *pout* (I'd suggest looking into atan2(y,x)...)

Remember that there are 2π radians in a whole circle (360°) so to convert from degrees to radians you multiply by π and divide by 180.
  sin-1 x
inverse sine/arcsine of x (result is measured in radians) asin(x) Similar to above, to convert from radians to degrees for the user, you'd multiply by 180 and divide by π.

Triangles and Circles and Waves...Oh, My!

Note that all math library functions assume they are receiving floating point arguments — double actually. Do NOT pass them whole valued arguments if at all possible (use a typecast if necessary).

Also note that all trigonometric functions either accept or return values measured in radians. You should always read from/print to the user in degrees (°) and convert to radians for calling the built-in trig functions. Likewise convert back from radians after an inverse trig operation for display for to the user. (The two main other trig functions besides sin are supported in a similar way: cos(), acos(), tan(), and atan()).)

BTW, there is also an atan2(y,x) function that will calculate the inverse tangent of y/x but use the signs of x and y to determine the quadrant of the angle. Instead of a standard range of (-π/2, π/2), its range is [-π, π]. I'd recommend its use to create a nice constant to represent π like so:

    const double PI = atan2(0.0, -1.0);

The Well-Rounded Programmer Knows

Note that there is no rounding function provided. Although some compilers have provided such functions, we'll not be using them — as they are not standard nor portable. Instead, we'll use the following formula which evaluates to the nearest whole value to x:

    floor(x + 0.5)

The reason this works is that floor() is essentially the same function as what we commonly think of as 'rounding to the nearest whole number' except that it has been translated half a step to the right. Or, in other words, rounding is the translation of floor() by 0.5 units to the left. (We recall from algebra that translation to the left occurs as adding to the incoming independent variable's value a non-negative quantity representing the number of units to shift...um. Yeah...it sounded so much better with a pretty graph to go along. I'll look for some graphs, but until then, pull out your old algebra book and flip through the translation section of the function chapter.) That is, if you move the graph of f(x) to the left by a units, you get the graph of f(x+a). (And if you move instead to the right by a units, you get the graph of f(x-a).)

But what if you need to round not just to the nearest whole number (the 1's place), but maybe to a different digit position (say the hundredths — 0.01), try this formula:

    floor(x / place + 0.5) * place

Here place represents the desired decimal place or digit position you'd like to round your number to. So, if you want to round 3456.128 to the nearest 0.01, you'd divide it by 0.01 — shifting the decimal place right 2 positions (dividing by a fraction is like multiplying by its reciprocal; here the reciprocal of 0.01 is 100): 345612.8. Now we add the 0.5 and take the floor() to round it: 345613. Finally, we multiply this result by 0.01 — shifting the decimal place left 2 positions again: 3456.13.

This will work for places that are any power of 10: 100, 1, 0.1, 10000, etc. In fact, this works even if 'place' is not a power of 10. You can round to the nearest multiple of 5, round to the nearest 25, or even round to the nearest half by using an appropriate value for place. (For the examples, those would be 5, 25, and 0.5 respectively. *grin*)

But there are those folks that don't really understand rounding all that well. And there are also those times where you don't really want to round, but rather want to force a value up or down to the next place. So, for such occasions, here's a handy chart:

I desire to...I will code...
force x down to the next lower multiple of place floor(x/place)*place
round x to the nearest multiple of place floor(x/place+.5)*place
force x up to the next higher multiple of place ceil(x/place)*place

But Life's More Than Numbers

Other libraries help to do more life-oriented things:

Character Manipulation Library: cctype

FunctionMeaning Notes
toupper(c) returns uppercase version of c if c is not a letter, its value is simply returned

unless it is used in an assignment:

 
   char ch_var;

   ch_var = toupper(ch_var);
   string s_var;

   s_var[0] = toupper(s_var[0]);
 

its returned value will almost certainly be noticed to be not truly a character, but rather the integer equivalent — its ASCII code; (the compiler silently performs an automatic type-cast during such assignments — called coercion of the type; otherwise you'd get a warning much like the one we got when we assigned a double calculation result to an integral type (short, was not it?) memory location)

to fix this, simply use your own type-cast:

    cout << static_cast<char>(toupper('a'));
tolower(c) returns lowercase version of c if c is not a letter, its value is simply returned

unless it is used in an assignment:

 
   char ch_var;

   ch_var = tolower(ch_var);
   string s_var;

   s_var[0] = tolower(s_var[0]);
 

its returned value will almost certainly be noticed to be not truly a character, but rather the integer equivalent — its ASCII code; (the compiler silently performs an automatic type-cast during such assignments — called coercion of the type; otherwise you'd get a warning much like the one we got when we assigned a double calculation result to an integral type (short, was not it?) memory location)

to fix this, simply use your own type-cast:

    cout << static_cast<char>(tolower('A'));
isalpha(c) returns true if c is in ['A'..'Z','a'..'z'] (is alphabetic) if c is not a letter, false is returned
isdigit(c) returns true if c is in ['0'..'9'] (is a digit) if c is not a digit, false is returned
isalnum(c) returns true if c is in ['A'..'Z','a'..'z','0'..'9'] (is alpha-numeric) if c is not a letter or digit, false is returned
isspace(c) returns true if c is in ['\n','\t','\r',' ',...] (is spacing) if c is not spacing, false is returned

Different systems define different spacing values, the ones listed are the most common. Other values may not be seen as spacing on all systems.
ispunct(c) returns true if c is in ['.',',',';','?',...] (is punctuation) if c is not punctuation, false is returned

Different systems define different punctuation values, the ones listed are merely the start of the list. However, note that some values may not be seen as punctuation on all systems.

Time Library: ctime

FunctionMeaning Notes
time(nullptr) returns the number of seconds elapsed since [the first] midnight (of January 1, 1970 — a date known as the Unix epochGMT) The argument value nullptr should always be passed to the time function. The count of seconds does not account for daylight savings time. The count of seconds may or may not include leap days (so you should experiment to find this out for your system). It seems highly doubtful that it includes leap seconds. (Maybe you should do some research about it...*shrug* It'd count just like a biography report for extra credit...)

Standard Library: cstdlib

FunctionMeaning Notes
rand() returns a pseudo-random number This value is chosen from a long sequence by a formula based on the current position within the sequence. The formula uses math tricks to make the sequence appear random to humans.

Note that this function takes no arguments. The parentheses must still be present, however, to tell the compiler to call this function. For more on random values, see the other notes.
srand(n) starts the random number sequence position at n This function returns no value — simply alters the current position within the possible outcomes of the random number generator (rand).

To make the random sequence change from run to run of your program, though, you must start differently each time. Toward this end, we use nested function calls srand(time(nullptr)) to make the sequence start at a position determined by the current time of day. For more on random values, see the other notes.
abs(n) returns the absolute value of its integer argument This version works on int type values. Since we do not use int, we'll use it for short type values instead.
labs(n) returns the absolute value of its integer argument This version works on long type values.

Input/Output Stream Library: iostream

FunctionMeaning Notes
cout.setf (f) set the output flag f to 'waving' (on) This makes cout's behavior change in subtle ways. Normally, for instance, cout will decide based on the magnitude of a floating-point value whether it should use scientific notation (with the E) or normal (aka the decimal place is fixed after the one's place and not allowed to 'float' around to make) notation for its display. However, by passing either ios_base::fixed or ios_base::scientific to the cout.setf() function, you can force it to always use one behavior or the other.

Once a flag is 'set' (or on/waving), it stays that way until you call cout.unsetf() (see) or cout.setf() with another flag argument that affects the same type of behavior.

Other flags you can un/set are given in the constants section below.
cout.unsetf(f) set the output flag f to 'not waving' (off) This attempts to change cout's behavior back to 'normal' but can not. We'll learn how to reset an output stream's formatting bahavior in CSC122.
cout.precision(n) make floating-point values print showing n digits of precision (when in scientific display mode) or n decimal places (when in fixed display mode) Handy for lining up columns of tables, but wo not work without the flag ios_base::showpoint. Normally, you see, cout will simply not print trailing zeros — even if you've specified a fixed notation output and, say, 2 decimal places! With ios_base::showpoint on, however, cout will always show the decimal point and trailing zeros.
cout.width(n) make the next value output n characters wide (if not already that wide) Unless the next value that is printed by cout is already greater than or equal to n characters worth of data, the effect of having called this function just before that output will be to add a number of filling characters to the 'output field' so that the overall width of the output material is n characters.

The filling character is normally a space (' '), but can be changed with either cout.fill() (see next) or the setfill manipulator.
cout.fill(c) when an item is narrower than its printing width (see the setw manipulator below), use the character c to fill in the extra positions The 'fill character' is normally a space (' '), but you can set it to be a dot ('.'), a star ('*'), or anything you like, really.
cin.ignore() ignore (skip over) a single character from the input buffer This function throws away, walks past, skips over...just plain ignores the next character that is in the input buffer. It does not discriminate based on whitespace-ness as extraction (>>) does, but takes any character — letter, symbol, digit, spacing, ...anything!
cin.ignore(n,c) ignore (skip over) characters from input buffer This function returns no value but accepts two arguments. One tells a count of how many characters to ignore. The second tells a character which, once seen, causes the ignoring to terminate/stop. When either of these two conditions are met (it has ignored the specified number of characters or it has just ignored the specific character), cin.ignore() stops.

Special: When the count given is numeric_limits<streamsize>::max() (see the constants section below), cin should ignore until the termination character is found (and extracted) — it will not bother to check for that specific number of characters having been ignored. After all, to the computer, is not numeric_limits<streamsize>::max() kind of like ∞?

Input/Output Manipulation Library: iomanip

ManipulatorMeaning Notes
setprecision(n) set precision or decimal places for printing floating-point values This manipulator makes the output stream put n digits of precision with floating-point values it prints in e-notation or n decimal places on a floating-point value it prints with normal notation.
setfill(c) set character with which to fill unused field width This manipulator makes the output stream fill any requested field width (see the width function of cout above or the setw manipulator here) that is not used for displaying actual data with the character c. (The default is for the stream to fill unused field width with spaces (' ').)
scientific always print floating-point in e-notation (3e-2) rather than normal notation (0.03) Sets a flag so that floating-point numbers will print as in science and engineering rather than just when they are too large or too small.

(See also the section below for constants and above for the setf function of cout.)
fixed always print floating-point in normal notation (300) rather than e-notation (3e2) Sets a flag so that floating-point numbers will print as we normally expect them to (instead of sometimes in scientific/e- notation).

(See also the section below for constants and above for the setf function of cout.)
setw(n) make the width of the next value output be n characters (or more if the next value is too large to fit in n characters) Immediately after printing the next value in that width, the output stream will forget the width setting and go back to using just enough characters to display the value.

You can use this on input streams as well, but it is tricky and I do not recommend it!
dec treat all input/output on this stream as base 10 This manipulator alters the default behavior of input streams to guess the base of information as it reads it (leading 0, leading 0x, etc.). (Some compilers already use strict base 10 input, but others are behind in their standards compliance. By always using dec you make your program safely portable without hassle.)

It is used like this:

    #include <iomanip>

    int main(void)
    {
        // ...
        cin >> dec;
        // ...
        return 0;
    }
hex treat all input/output on this stream as base 16 As with dec above, but base 16 values are assumed (implying you do not need to type the '0x' as you would normally).
oct treat all input/output on this stream as base 8 As with dec above, but base 8 values are assumed (implying you do not need to type the '0' as you would normally).

Constants in the Libraries

Constant NameMeaning Library
nullptr the argument for time() cstddef (and many others)
RAND_MAX the maximum random value generated by rand cstdlib
INT_MAX the maximum value that can be stored in a (signed) int climits
INT_MIN the minimum value that can be stored in a (signed) int climits
UINT_MAX the maximum value that can be stored in an unsigned int climits
LONG_MAX the maximum value that can be stored in a (signed) long climits
LONG_MIN the minimum value that can be stored in a (signed) long climits
ULONG_MAX the maximum value that can be stored in an unsigned long climits
SHRT_MAX the maximum value that can be stored in a (signed) short climits
SHRT_MIN the minimum value that can be stored in a (signed) short climits
USHRT_MAX the maximum value that can be stored in an unsigned short climits
CHAR_MAX the maximum value that can be stored in a (signed) char climits
CHAR_MIN the minimum value that can be stored in a (signed) char climits
UCHAR_MAX the maximum value that can be stored in an unsigned char climits
DBL_MAX the maximum [positive] value that can be stored in a double cfloat
DBL_MIN the minimum [positive] value that can be stored in a double cfloat
DBL_EPSILON the closest two double values can be and still be recognizably distinct cfloat
DBL_MAX_10_EXP approximately the largest exponent of 10 that a double can represent cfloat
DBL_MIN_10_EXP approximately the smallest exponent of 10 that a double can represent cfloat
DBL_DIG an approximate number of precise digits you can expect from a double value cfloat
LDBL_MAX the maximum [positive] value that can be stored in a long double cfloat
LDBL_MIN the minimum [positive] value that can be stored in a long double cfloat
LDBL_EPSILON the closest two long double values can be and still be recognizably distinct cfloat
LDBL_MAX_10_EXP approximately the largest exponent of 10 that a long double can represent cfloat
LDBL_MIN_10_EXP approximately the smallest exponent of 10 that a long double can represent cfloat
LDBL_DIG an approximate number of precise digits you can expect from a long double value cfloat
FLT_MAX the maximum [positive] value that can be stored in a float cfloat
FLT_MIN the minimum [positive] value that can be stored in a float cfloat
FLT_EPSILON the closest two float values can be and still be recognizably distinct cfloat
FLT_MAX_10_EXP approximately the largest exponent of 10 that a float can represent cfloat
FLT_MIN_10_EXP approximately the smallest exponent of 10 that a float can represent cfloat
FLT_DIG an approximate number of precise digits you can expect from a float value cfloat
ios_base::fixed flag to control whether floating point values are displayed in fixed (normal/non-scientific) notation or not iostream
ios_base::scientific flag to control whether floating point values are displayed in scientific ('e') notation or not iostream
ios_base::showpoint flag to control whether floating point values whose decimal places are merely 0's should display them anyway or not iostream

Using Functions

Some examples: