Software Design Using C++Arithmetic and Formatting of Output in C++ArithmeticArithmetic is often used to compute an answer that we need to print, store in a variable, write to a file, etc. For example, to convert a Centigrade temperature to Farenheit we might use the following C++ assignment statement. Here CentigradeTemp is the Centigrade temperature known in advance and FarenheitTemp is the calculated Farenheit temperature. Notice how closely this C++ statement corresponds to the usual mathematical formula.
The overall form of the above assignment statement is "variable = expression". As you know, an assignment statement takes the value of the expression on the right hand side of the = operator and copies that value into the variable on the left hand side. The expression on the right hand side can be a very simple one, such as a number, a variable, or a constant. (You will learn about constants in a later section of these web pages. Follow the link in the previous sentence if you want to look at them now.) An expression can also be more complex, such as the one used above. That one used the multiplication operator *, the division operator /, as well as the addition operator +. It also contained three literal numbers and one variable. You probably realize that it is also important to know in what order the arithmetic operators are done. Happily, C++ generally follows the same order of operations used in ordinary algebra. Thus, in our FarenheitTemp calculation, we do the * first, the / second, and the + last. This is because multiplication and division come before addition and subtraction. Multiplication and division have the same precedence, so they are simply done in left to right order. The table below gives some additional examples of assignment statements. The expressions on the right hand sides vary in complexity. The variables and constants use in the table might be declared as follows:
Note how simple it is to set up a constant such as TAXRATE. If the constant is declared inside of a function, then it is only available in that function. (That is, it is a local constant.) If the constant is set up near the top of a C++ file, before any of the functions, then that constant is global (is available in any of the functions of this file).
The first example in the table copies the literal number 156 into the variable Num. The second example copies the literal character 'B' into the char variable Ch. In both cases, it might be better to use a constant instead of a literal value. The third example shows how a constant might be used. It copies the TAXRATE constant into the float variable Value. The next example copies the value of the LastIndex variable into the int variable k. The next-to-last example finds the value of the expression Total / Count, which is the quotient when Total is divided by Count, and copies that into the float variable Average. Since Total is a float and Count is an int, floating point division is used. (If both values had been integers, then integer division would have been used. This would result in a whole number quotient. Essentially this is the floating point quotient with the part following the decimal point truncated off.) This example shows the typical way to calculate an average, though we have to be careful if Count could be zero. If that could happen we would need to use an IF statement to skip the division in the case when Count is zero. In C++ as in ordinary algebra, division by zero is not allowed. Finally, the last example shows one way to increment a variable by 1. The value of the expression on the right side is one bigger than Count. That value is then assigned back into Count, changing it to one bigger than it had been. Below we will see a shorter way to increment a variable. Let's look at a more complete example, the arithmetic.cpp test program. This program computes and prints various nonsense values just to show how to do arithmetic, either in an assignment statement or in an output statement. (Recall that you can directly output the value of an expression.) Take a look at this program under the above link and then examine the output as shown here:
In Test 1 above, In Test 2, the ++ operator is used to increment a variable. The ++ can either be placed before or after the variable, though the meaning is slightly different depending on where the ++ is placed. Here we use IntAnswer++ on a line by itself, with the ++ after the variable. When the ++ comes after the variable, the incrementing is done after anything else in the command. Since we have nothing else on this line, all that IntAnswer++ does is to increment the value of IntAnswer by 1. Thus, IntAnswer is given the value 10, which we see when the next command prints it. In Test 3, IntAnswer++ is put inside of an output statement. This time there is more to the command than the incrementing, so all of the other stuff (namely, the output) is done first and then IntAnswer is incremented. That is why this example prints 50 when it outputs IntAnswer++ and only shows 51 in a later command that outputs IntAnswer. Test 4 is quite similar to Test 3. However, it puts the ++ in front of the variable. Having the ++ before the variable means that the incrementing of the variable happens before anything else in the command. Since our command has ++IntAnswer inside of an output statement, the incrementing of IntAnswer to 23 is done before the output is done. Thus we see 23 in the output.
Test 5 prints the value of the expression
Test 6 is almost the same as Test 5. The only change is that it puts parentheses around
In Test 7 we do
Test 8 might also surprise you a bit. It does
Finally, Test 9 shows you how to get that elusive 3.75 value if you really want it!
Use floating point values (or one float and one int if you are willing to settle for mixed-mode
arithmetic). The assignment statement Precedence of OperatorsAs mentioned above, we often need to worry about which operator comes first when writing arithmetic expressions in our C++ programs. Since the most common arithmetic operators follow the same precedence rules as in algebra, you will find that many of the typical expressions that you need are natural to write. Sometimes, however, you may need to use less well-known operators. The following table should help you in those cases. It shown many (but not all) of the C++ operators for arithmetic, logical operations, etc. Those with priority 1 are handled before all of those with a larger precedence number. Those with priority 2 come after those with priority 1 but before all of the others. Those with the same priority are generally handled in a left to right fashion. Parentheses can be used to group items so that whatever is inside is handled before other items. If there are parentheses inside of parentheses it is the innermost set of parentheses that is handled first.
Formatting of OutputThere are many ways of formatting your output to make it look nice on the screen. If you wish to print a number or other item in a certain field width you can use setw. To use it you must include the iomanip header. You do this in the same way that you include the iostream header. For example, you might place the following at the top of your code file:
Then to get something printed in a field having a certain width, say 8 characters wide, you place setw(8) inside your output statement. For example, suppose that you want to print the integer Value in a field 8 characters wide and follow that by printing the integer Total in a field also 8 characters wide. You would use something like this:
Notice that we had to issue the setw(8) command twice, once before each item that we wanted to print in a field that was 8 wide. You can also print a string in a field of a certain width with setw. For example, we could print the literal strings "Value" and "Total" each in a field 8 characters wide. We might follow that by printing the values in the variables Value and Total. The code for this might be:
For example, if 85 and 443 are the values in variables Value and Total, then the above section of code would print things nicely lined up in columns as follows. Blanks are printed in front of each item as needed to pad the width to the desired width of 8.
To format floating point numbers nicely, it helps to print each of them with the same number of decimal places. This can be handled by placing the following code (just once) before the printing of the floats:
The As an example, consider the following program fragment. Assuming that we have included the iomanip header so that we can use setw, and assuming that the rest of the program is set up correctly, this section of code produces the output shown in the box below that follow the code.
Notice that the second set of output prints the numbers so that their decimal points are aligned vertically:
Rounding a NumberLet's calculate something more useful than most of our short examples did so far on this page. Sometimes we need to round a number to a certain number of decimal places (often 2). If all we want to do is to round the printed number we can simply use precision
as in the previous example. However, this does not round the actual number stored in a variable.
If we need to store a rounded value in a variable, we need to do some arithmetic to compute
the rounded value.
Take a look at the rounding.cpp example in this regard. It contains 4 somewhat different rounding functions and prints a list of numbers and their rounded values as produced by these rounding functions. In this test program, all we do is to print each rounded value. For example, we do something like this:
If we want to also store the rounded value, perhaps back into the original variable, we would use code like this:
Returning to the rounding.cpp example itself, the output produced by this test program is as follows:
Notice that all 4 of the rounding functions produce the same results. Let's examine these rounding functions one by one.
The Round1 function take Value, the floating point number to be rounded, and multiplies it by 100. For example, if Value contains 34.708, the variable Product is assigned 3470.8 as its value. The integer variable Whole is then assigned the whole number part of this. In other words, it gets 3470 as its value. Notice the use of the static cast to an int as one way to convert the float to an int. The difference between Product and Whole, namely 0.8 in our example, is placed into the variable Fraction. We next want to see if Fraction is 0.5 or bigger, and then round Value up if this is the case. One way to do this is to check if twice Fraction is greater or equal to 1. In our example, twice Fraction is 1.6, so that this is true. In such a case we round up by returning in the function name the value of (Whole + 1.0) / 100.0, which in our example gives (3470 + 1) / 100.0 = 3471 / 100.0 = 34.71, which is the correct rounded value. If the original number in Value had been something like 5.6738, then Product would have been 567.38, Whole would have been 567, Fraction would have been 0.38, and since twice Fraction would have been 0.79 which is less than 1, we would have returned as our rounded answer Whole / 100.0 = 567 / 100.0 = 5.67, which is the correct result. (Since 0.38 is less than 0.5 we want to round down to 5.67 and not round up to 5.68.) Note the mixed-mode arithmetic in that Whole is an int but we divide by a float. This means that floating point division is used.
The Round2 function accomplishes the same rounding task with much less code. Let's trace it on our same two examples. In the first one, Value is 34.708, so that Temp is assigned 3470.8 + 0.5 = 3471.3. However, since Temp is an integer variable, the .3 is cut off and Temp gets 3471 as its value. (Note that we could have used a cast here, but it works OK without, though your compiler may give you a warning.) Thus we return Temp / 100.0 = 3471 / 100.0 = 34.71 as desired. In our second example, Value is 5.6738, so that Temp is assigned 567.35 + 0.5 = 567.85, with the result that Temp contains 567, since it is an int variable. The function then returns 567 / 100.0 = 5.67 in the function name.
With the Round3 function, a second parameter was included in order to specify the number of decimal places to which to round the answer. In expected use, this NumPlaces parameter should be a positive integer, though the function will also work with a value of zero for NumPlaces, rounding Value to the nearest whole number. Note that the pow function is used to compute 10.0 to the NumPlaces power. This is a library function and requires that you include the cmath header. When NumPlaces is 2, pow(10.0, NumPlaces) is 100.0 so that the Factor that we multiply Value by is 100.0, just like in the Round2 function. In fact, the computations on the last 2 lines of Round3 are essentially the same as those in Round2. Let's trace Round3 in the special case where NumPlaces is 0. Let's use the number 12.783 for Value. Note that Factor is given the value 1.0, Temp is assigned 12.783 + 0.5 = 13.283, so that Temp gets the value 13. (Once again, this is because Temp is an int.) Round3 then returns 13 / 1.0 = 13.0 in the function name. If we instead use 396.4 for Value but stay with 0 for NumPlaces, Temp is assigned 396.4 + 0.5 = 396.9, so that Temp gets the truncated value of 396. Round3 then returns 396 / 1.0 = 396.0 in the function name.
Our last example rounding function, Round4, is mostly the same as Round3. The only difference is that it does not use the pow function to compute 10 to the NumPlaces power. It uses a FOR loop to multiply 1 by the appropriate number of copies of 10. The rest of the rounding code is exactly the same as in the Round3 function. Back to the main page for Software Design Using C++ |