Arithmetic Operators
Chapter Fifteen
Syllabus topic 2, "Type of operators: Arithmetic operators, relational and logical operators, Increment and Decrement operators, assignment operators, the conditional operator, Assignment operators and expression, Precedence and order of Evaluation Block Structure, Initialization, C Preprocessor"
Pages 69 to 73 of 222
In one line
C has five arithmetic operators, +, -, *, / and %, and the two that need care are /, because on two integers it throws the fraction away, and %, because it works only on integers.
The five
| Operator | Name | a = 17, b = 5 |
|---|---|---|
+ | addition | a + b is 22 |
- | subtraction | a - b is 12 |
* | multiplication | a * b is 85 |
/ | division | a / b is 3 |
% | remainder, or modulus | a % b is 2 |
All five are binary: they take two operands. - is also available as a unary operator, -x, which gives the negation, and there is a unary +x, which does nothing useful and exists for symmetry.
#include <stdio.h>
int main(void)
{
int a = 17, b = 5;
printf("a = %d, b = %d\n", a, b);
printf("a + b = %d\n", a + b);
printf("a - b = %d\n", a - b);
printf("a * b = %d\n", a * b);
printf("a / b = %d <- integer division\n", a / b);
printf("a %% b = %d <- remainder\n", a % b);
printf("-a = %d\n", -a);
printf("and the identity: (a / b) * b + (a %% b) = %d\n",
(a / b) * b + (a % b));
return 0;
}a = 17, b = 5
a + b = 22
a - b = 12
a * b = 85
a / b = 3 <- integer division
a % b = 2 <- remainder
-a = -17
and the identity: (a / b) * b + (a % b) = 17The last line is the identity that defines the pair: (a / b) * b + (a % b) is always a. If you can remember that, you can always work out what % must give.
Integer division, which is the whole difficulty
If both operands are integers, / is integer division: the fractional part is discarded and the answer is an integer. 17 / 5 is 3, not 3.4, and not 3 with something stored elsewhere.
To get a fraction, at least one operand must be a floating-point type. Chapter 14 is the rule; this is how it looks in practice:
#include <stdio.h>
int main(void)
{
int a = 17, b = 5;
printf("a / b = %d\n", a / b);
printf("(double) a / b = %.4f\n", (double) a / b);
printf("a / (double) b = %.4f\n", a / (double) b);
printf("a / 5.0 = %.4f\n", a / 5.0);
printf("1 / 2 = %d <- both integers\n", 1 / 2);
printf("1.0 / 2 = %.4f\n", 1.0 / 2);
return 0;
}Arithmetic Operators
a / b = 3
(double) a / b = 3.4000
a / (double) b = 3.4000
a / 5.0 = 3.4000
1 / 2 = 0 <- both integers
1.0 / 2 = 0.50001 / 2 is 0. This turns up inside larger expressions and is easy to miss: x 1 / 2 is (x 1) / 2, which for an integer x of 7 is 3, while x (1 / 2) is x 0, which is 0. Neither is 3.5.
The remainder operator
% gives what is left after integer division. It requires both operands to be integers. 7.5 % 2 does not compile; there is fmod in <math.h> for floating-point remainders.
What % is actually used for is worth listing, because these five uses cover nearly every appearance of it in this course:
- Is it divisible?
n % 2 == 0tests even.year % 4 == 0is the first part of the leap-year test in chapter 16. - Extract the last digit.
n % 10. Withn / 10to remove it, that is the whole of the reverse-the-digits practical in chapter 27. - Wrap a value into a range.
(i + 1) % nsteps round a circle ofnpositions. - Split a quantity into units. Seconds into minutes and seconds, paise into rupees and paise.
- Test a multiple.
i % 5 == 0to print every fifth line.
#include <stdio.h>
int main(void)
{
int seconds = 3725;
printf("%d seconds is %d h %d m %d s\n",
seconds, seconds / 3600, (seconds / 60) % 60, seconds % 60);
printf("the last digit of 3725 is %d\n", 3725 % 10);
printf("3725 without its last digit is %d\n", 3725 / 10);
printf("is 3725 even? %d (1 means yes)\n", 3725 % 2 == 0);
return 0;
}3725 seconds is 1 h 2 m 5 s
the last digit of 3725 is 5
3725 without its last digit is 372
is 3725 even? 0 (1 means yes)Negative operands
Division truncates towards zero, so % takes the sign of the left-hand operand. This is fixed by the standard since C99 and it is worth checking once rather than guessing.
#include <stdio.h>
int main(void)
{
printf(" 17 / 5 = %3d 17 %% 5 = %3d\n", 17 / 5, 17 % 5);
printf("-17 / 5 = %3d -17 %% 5 = %3d\n", -17 / 5, -17 % 5);
printf(" 17 / -5 = %3d 17 %% -5 = %3d\n", 17 / -5, 17 % -5);
printf("-17 / -5 = %3d -17 %% -5 = %3d\n", -17 / -5, -17 % -5);
return 0;
} 17 / 5 = 3 17 % 5 = 2
-17 / 5 = -3 -17 % 5 = -2
17 / -5 = -3 17 % -5 = 2
-17 / -5 = 3 -17 % -5 = -2Arithmetic Operators
So -17 % 5 is -2, not 3. If you need a non-negative remainder for wrapping round a circle, write ((a % n) + n) % n.
Division by zero
Integer division by zero is undefined behaviour. Not zero, not an error you can catch, not infinity. On most machines the program is killed.
There is no way to recover from it afterwards, so the only correct handling is to test first:
if (count != 0) {
average = (double) total / count;
} else {
printf("no marks were entered\n");
}Floating-point division by zero is different: it is defined by the floating-point standard and gives infinity or a "not a number" value rather than killing the program. Do not rely on that. Test the divisor.
The practical: simple interest from input
MU's Practical 1(a) reads the principal, the rate and the number of years from the user and prints the simple interest. Here it is, with the input checked, which is the part that separates a program from a program that works.
#include <stdio.h>
int main(void)
{
double principal, rate, years;
printf("Enter principal, rate per year and number of years: ");
if (scanf("%lf %lf %lf", &principal, &rate, &years) != 3) {
printf("\nThose were not three numbers.\n");
return 1;
}
double interest = principal * rate * years / 100.0;
printf("\nPrincipal : %10.2f\n", principal);
printf("Rate per year : %10.2f %%\n", rate);
printf("Number of years : %10.2f\n", years);
printf("Simple interest : %10.2f\n", interest);
printf("Amount repayable : %10.2f\n", principal + interest);
return 0;
}15000 8.5 2Enter principal, rate per year and number of years:
Principal : 15000.00
Rate per year : 8.50 %
Number of years : 2.00
Simple interest : 2550.00
Amount repayable : 17550.00Four things in that program are the difference between a pass and a good mark.
%lfinscanf, not%f.scanftakes an address and does no promotion, so%fmeans "afloat" and%lfmeans "adouble". Passing adouble *to%fwrites four bytes into an eight-byte object and is a real bug. Inprintfthe opposite is true:%fis right for both, because afloatargument is promoted todouble.scanfreturns a count, the number of items it successfully read. Checking it against 3 is the whole of the input validation, and it is one line./ 100.0, not/ 100. Here it makes no difference because the operands are alreadydouble, but writing100.0is the habit that saves you when they are not.%%in the format string prints one per cent sign. A single%starts a conversion.
Arithmetic Operators
For the algorithm and flowchart that MU asks for in the same practical, see chapter 2.
Arithmetic on characters, which is legal and useful
A char is a small integer, so all five operators work on it. Two uses are standard:
#include <stdio.h>
int main(void)
{
char digit = '7';
char lower = 'q';
printf("'7' as a number is %d\n", digit - '0');
printf("'q' in upper case is %c\n", lower - 'a' + 'A');
printf("the 5th letter of the alphabet is %c\n", 'A' + 4);
return 0;
}'7' as a number is 7
'q' in upper case is Q
the 5th letter of the alphabet is Elower - 'a' + 'A' works on any machine whose letters are consecutive, which is every machine you will use, but the standard does not guarantee it. toupper from <ctype.h> is the portable form and is chapter 34.
What this does NOT mean
/ is not always integer division. It is integer division only when both operands are integer types. The operator is the same; the operands decide.
% is not "percent". It is the remainder after integer division. To compute a percentage you divide and multiply by 100, in floating point.
% does not work on double. Use fmod from <math.h>.
There is no exponentiation operator in C. 2 ^ 3 is not 8; ^ is bitwise exclusive-or and gives 1. Use pow(2, 3) from <math.h>, or multiply, and for a square prefer x * x to pow(x, 2).
a % b for negative a is not always positive. It takes the sign of a.
Integer overflow is not "wrapping round". For signed integers it is undefined behaviour, unlike unsigned arithmetic which is defined to wrap. INT_MAX + 1 is not reliably INT_MIN.
Quick revision
- Five operators:
+ - * / %. Unary-as well. /on two integers discards the fraction. Make one operand adoublefor a real quotient.%needs integer operands;fmodis the floating-point version.(a / b) * b + (a % b)is alwaysa.- Division truncates towards zero, so
%takes the sign of the left operand:-17 % 5is -2. - Non-negative wrap:
((a % n) + n) % n. - Integer division by zero is undefined behaviour. Test the divisor.
- No exponentiation operator.
^is bitwise exclusive-or. - Signed overflow is undefined; unsigned arithmetic wraps by definition.
- In
scanf, adoubleneeds%lf. Inprintf,%fserves bothfloatanddouble.
Test yourself
1. What are 17 / 5, 17 % 5, 17.0 / 5 and 17 % 5.0?
Arithmetic Operators
3, 2, 3.4, and the last does not compile: % requires integer operands.
2. Write an expression that gives the tens digit of an integer n.
(n / 10) % 10.
3. What is -7 % 3, and why?
-1. Division truncates towards zero, so -7 / 3 is -2, and the identity (-2) * 3 + (-1) gives -7.
4. A program must print an average to two decimal places from int total and int count. Write the statement.
if (count != 0) printf("%.2f\n", (double) total / count);5. Convert 3725 seconds into hours, minutes and seconds using only / and %.
Hours 3725 / 3600, minutes (3725 / 60) % 60, seconds 3725 % 60, giving 1 h 2 m 5 s.
6. Why is %lf needed in scanf but not in printf?
scanf receives a pointer and performs no conversion, so the length modifier tells it whether the target is a float or a double. In printf a float argument is automatically promoted to double, so %f handles both.
7. What does 2 ^ 3 give in C?
^is bitwise exclusive-or, not exponentiation. Two is10and three is11in binary, and their exclusive-or is01.
What can be asked on this, and how to answer it
"Explain the arithmetic operators in C with examples." Give the five with a worked value each, then spend the rest of the answer on the two that need it: integer division and its fix, and the remainder operator with its integer-only restriction and the identity. That is the shape the marks follow.
"What is the difference between / and %?" / gives the quotient and % the remainder of an integer division. / works on any arithmetic type and is integer division only when both operands are integers; % requires integer operands. (a / b) * b + (a % b) is a.
"Write a program to calculate simple interest taking principal, rate and years as input." Give this chapter's program. The examiner's follow-up is nearly always why %lf, or what happens if the user types a letter, so keep the scanf check in.
"What is the output of printf("%d", 5/22)?" 4. / and have equal precedence and group left to right, so it is (5 / 2) 2, which is 2 2. Chapter 20 is precedence in full.
"Write a program to convert a given number of seconds into hours, minutes and seconds." Give the three expressions above and say in one line why % 60 is needed on the minutes: dividing by 60 gives total minutes, and the hours must be taken out of it.
The rest of this subject
These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.