2.6 Converting Formulas to C++ Statements

Time: 00:06:37 | Download: Large Small | Streaming | Slides (PDF)

FORTRAN, the first high-level computer programming language was written precisely to make it easy to translate mathematical formulas into computer code (FORTRAN is an acronym for FORmula TRANslation). From FORTRAN forward, most computer programming languages have made translating formulas into code relatively easy. Some of the needed operations, such as addition, subtraction, multiplication, and division, are implemented directly by the compiler, but other operations, such as representing π or evaluating expressions such as 35 or √2 are left up to libraries that the linker automatically links to the executable program.

This section offers some general guidelines for converting mathematical formulas into C++ code.

Variables

Mathematical formulas typically use a single character to represent a variable (but be careful as formulas can use multiple characters too). Variables are sometimes accompanied by superscripts and subscripts. Superscripts (e.g., xn ) usually denote an exponentiation operation (described below). Subscripts are often used to distinguish between distinct but related variables:
A new value m and an initial value m0
Variables in a recurrence formula: Fn = Fn-1 + Fn-2

C++ doesn't allow subscripts in variable names, so, while being careful to make sure each variable name is unique and legal, simply make the subscript part of the variable name: fn, fn1, and fn2

Multiplication

Mathematical formulas often denote multiplication by juxtaposing variables (i.e., placing the variables adjacent to one another), but C++ requires that multiplication be explicitly denoted with the * operator. For example, a mathematical formula might be written as PV but the same formula is programmed in C++ as P * V. It is easier to remember the difference between mathematics and C++ if you recall that variables in mathematical formulas are typically denoted by one main character (which is sometimes decorated with sub- or super-scripts or other notations), but variables used in computer programs are often spelled out to make their meaning more clear: pressure * volume.

Division

One notation for division in mathematical formulas is similar to the operator used in C++. For example, the formula P/T is "converted" to C++ as P/T or as pressure / temperature. But what about a formula like this:

P over the quantity t1 - t2

Based on the similarities between mathematics and C++, our first, naive attempt to convert the formula to C++ might be to simply work from left to right, which would result in a deceptively incorrect conversion: P / T2 - T1. The horizontal line represents the division operation, but it also implicitly groups together T2-T1 just as if the expression was surrounded by parentheses: (T2-T1). So, assuming that a C++ program defines the variables double P, T1, T2;, a correct conversion of the above formula into a C++ expression is:

P / (T2 - T1)

Grouping parentheses in the second attempt force the subtraction to take place before the division.

Integer Division

If both the dividend (the left hand operand) and the divisor (the right hand operand) are integers, then the operation is carried out using integer arithmetic, which does not support floating point values. (This is not an error nor is it a shortcoming with the language - it is exactly what is needed in many situations.) Be cautions of formulas like this:

The formula for converting a tempurature given in Fahrenheit to Celcius:
5/9(f-32)

The result of 5/9 is 0 and the result of 9/5 is 1 (no fractional part in either case). Given the definitions double c, f; the above formula can be successfully converted into C++ in several ways:

  1. c = 5.0 / 9.0 * (f - 32);
  2. c = 5 * (f - 32) / 9;
  3. c = 5.0 / 9 * (f - 32);
  4. c = 5 / 9.0 * (f - 32);
  5. c = (double)5 / 9 * (f - 32);
  6. c = double(5) / 9 * (f - 32);
  7. c = 5 / (double)9 * (f - 32);
  8. c = 5 / double(9) * (f - 32);

Try to explain to yourself why each of these statements work. Finally, the ANSI standard is that integer division results in truncation (i.e., values are NOT rounded). So the result of 999/1000 is still 0.

Unary Minus / Negation Operator

Everyone is familiar with arithmetic subtraction, which is implemented with the binary minus operator: x - 5. But there is also a unary version of - known as the negation operator. Sometimes when a new programmer sees an expression in a mathematical formula like -N they are tempted to implement it in C++ code as -1 * N. Although this works perfectly well, it is also unnecessarily complex and awkward. Assuming that a program defines the variable N, then the arithmetic expression -N is "converted" into C++ with the negation operator as ‑N.

Converting more complex expressions that use the negation operator involves more algebra than it does programming. For example, the mathematical formula: -(a+b) carries over to C++ unchanged (again, assuming that the program defines two variables named a and b. But, using the rules of algebra, you could also rewrite the expression as -a-b (which exactly how it is rewritten in algebra too).

Header File

If you use any of the mathematics library functions or constants, remember to #include <cmath> and if you are writing code in Visual Studio and use any of the mathematics library constants (or if there is a chance that someone will compile your code with Visual Studio), then also remember to #define _USE_MATH_DEFINES at the top of each file that uses a constant.

Exponentiation (The pow Function)

For small, integral exponents, exponentiation can be accomplished by multiplying the number by itself:

x2 = x * x;
x3 = x * x * x;
x4 = x * x * x * x;
xn = x1 * x2 * . . . * xn;

However, this approach quickly becomes tedious and error prone for even small values of n. For larger values of n, a for loop can be used (but rarely is); for example, x57 can be translated into the following C++ code:

double exp = 1;
for (int i = 0; i < 57; i++)
	exp *= x;

However, for loops are unnecessarily cumbersome, inefficient, and will not work if the exponent is not a positive integer; for example x2/3, x-N, or xy where y is type double. In these cases, use the C++ math library pow function double pow(double base, double exponent). The pow function returns a double value, so if the result needs to be an integer, then then remember to cast the return value back to an int: (int)pow(2, 3);. The following formula calculates the periodic payment based on the principal, the periodic interest rate, and the number of periods

The formula for calculating a periodic payment based on the principal, the periodic interest rate, and the number of periods:
payment = PR/(1-(1+R) to the power of -N

The formula can be translated into the C++ code as:

payment = P * R / (1 - pow(1 + R, -N));

Notice that the expression 1 + R is the base and the expression -N is the exponent. These expressions are evaluated before the pow function is called and it is the values that these expressions represent that are passed as arguments to pow. The results of the expressions could have been stored in temporary variables but that is not necessary.

Square Root (The sqrt Function)

To convert a function involving a square root operation into C++, begin by converting the radical (√) into the C++ sqrt function. The horizontal line at the top of the radical acts as a grouping symbol, so everything under the radical goes inside the parentheses (i.e., is part of the sqrt function's arguments), and are evaluated before the function executes. It is illegal, both in mathematics and in C++, to attempt to take the square root of a negative number and the sqrt function will return strange values, such as -1.#IND or -1.#INF, whenever its argument evaluates to a negative value. If h, a, and b are variables defined in a C++ program, then the mathematical expression:

h times the square root of a squared plus b squared

is converted into the C++ code as:

h * sqrt(a*a + b*b)

or

h * sqrt(pow(a,2) + pow(b,2))

Symbols of Inclusion (i.e., Grouping)

Mathematical formulas usually use round parentheses for grouping, just like computer programming languages. But unlike programming languages, mathematical formulas can, and sometimes do, use other symbols to denote groups. This is most often done when multiple levels of grouping are required - using different symbols makes it easier to match the corresponding opening and closing symbols. After round parentheses, the most common symbol pair used in mathematical formulas are square brackets: [ and ]. Square brackets, or other grouping symbols, are used for entirely different purposes in C++ and so must be translated into round parentheses. Furthermore, the parentheses and commas used to form a function's argument list also act as grouping operators. That is, each argument expression is evaluated before the function is called (this helps to reduce the need for parentheses in C++ expressions, which helps to make the code easier to read). The following mathematical function may be translated in to C++ in several different ways.

A formula using both round parentheses and square brackets as gourping symbols.
the formula also implies multiplication by placing the variable F next to the opening square bracket.

Valid translations of the above formula include the following:

P = F * r / (pow(1 + r, n) - 1) / (1 + r);
P = F * r / (pow(1 + r, n) - 1) * 1 / (1 + r);
P = F * (r / (pow(1 + r, n) - 1)) * (1 / (1 + r));

It is possible, of course, to add more parentheses. For example, 1 + r could be enclosed in parentheses: (1 + r) and -n can be rewritten in several ways: -(n), -(n), -1 * n, or (-1 * n). While there is no absolutely correct number of parentheses, at some point extraneous parentheses begin to cause problems: they make it more difficult to read and understand a statement, make it more likely that the parentheses will become unbalanced, or that a parenthesis will be misplaced. Relying on operator precedence will help to keep the number of parentheses at a manageable level.