munotes®

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

OperatorNamea = 17, b = 5
+additiona + b is 22
-subtractiona - b is 12
*multiplicationa * b is 85
/divisiona / b is 3
%remainder, or modulusa % 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) = 17

The 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;
}
munotes.in69

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.5000

1 / 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:

  1. Is it divisible? n % 2 == 0 tests even. year % 4 == 0 is the first part of the leap-year test in chapter 16.
  2. Extract the last digit. n % 10. With n / 10 to remove it, that is the whole of the reverse-the-digits practical in chapter 27.
  3. Wrap a value into a range. (i + 1) % n steps round a circle of n positions.
  4. Split a quantity into units. Seconds into minutes and seconds, paise into rupees and paise.
  5. Test a multiple. i % 5 == 0 to 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 =  -2
munotes.in70

Arithmetic 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 2
Enter 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.00

Four things in that program are the difference between a pass and a good mark.

  • %lf in scanf, not %f. scanf takes an address and does no promotion, so %f means "a float " and %lf means "a double ". Passing a double * to %f writes four bytes into an eight-byte object and is a real bug. In printf the opposite is true: %f is right for both, because a float argument is promoted to double.
  • scanf returns 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 already double, but writing 100.0 is the habit that saves you when they are not.
  • %% in the format string prints one per cent sign. A single % starts a conversion.
munotes.in71

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 E

lower - '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 a double for a real quotient.
  • % needs integer operands; fmod is the floating-point version.
  • (a / b) * b + (a % b) is always a.
  • Division truncates towards zero, so % takes the sign of the left operand: -17 % 5 is -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, a double needs %lf. In printf, %f serves both float and double.

Test yourself

1. What are 17 / 5, 17 % 5, 17.0 / 5 and 17 % 5.0?

munotes.in72

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?

  1. ^ is bitwise exclusive-or, not exponentiation. Two is 10 and three is 11 in binary, and their exclusive-or is 01.

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.

munotes.in73

The rest of this subject

These notes are cut from the University's printed syllabus. Open the syllabus itself for the same subject.

Report or request
Done!