Skip to main content

Microcontrollers

Section 14.4 Arithmetic and Assignment Operations

The assignment and arithmetic operators perform core mathematical functions in C. The assignment operator (=) defines a value or variable by storing it in either program or data memory. The assignment operator should not be when changing values in a PORTx register! In this case, bitwise operators (defined below) should be used instead.

Subsection 14.4.1 Addition and Subtraction

The addition operation (+) calculates the sum of two numbers and subtraction (-) calculates the difference of two numbers. Note that while addition is commutative (\(a + b = b + a\)), subtraction is not (\(a - b \neq b - a\)), so care must be taken in ensuring the correct position of each operand.
Because subtraction in particular can lead to negative results, it is important to ensure that the correct datatype (signed or unsigned) is used to store the result of any operations.

Subsection 14.4.2 Multiplication and Division

The multiplication operation (*) calculates the product of two numbers and division (/) calculates the quotient of two numbers. Note that while multiplication is commutative (\(a * b = b * a\)), division is not (\(a / b \neq b / a\)), so care must be taken in ensuring the correct position of each operand.
When using integer datatypes, keep in mind that the microcontroller will truncate all values as integers. It is extremely important to keep this in mind when doing a sequence of math.

Example 14.4.1. Integer math error in division.

Consider a variable x that must be multiplied by 50 and divided by 3. The expected integer result of the operation will be 166 Multiplication must occur first, followed by division. If division occurs prior to multiplication, the first arithmetical result (x/50) will be truncated to an integer prior to completing the second operation (multiply that truncated integer by 3).
For example, consider when x = 10. Dividing first leads to the following (unexpected) result.
\begin{align*} (x / 3) * 50 \amp= \\ (10 / 3) \amp = 3\\ 3 * 50 \amp= 150 \end{align*}
Multiplying first leads to the following (expected) result.
\begin{align*} (x * 50) / 3 \amp= \\ (10 * 50) \amp = 500\\ 500 / 3 \amp= 166 \end{align*}
A second consideration in multiplication when using the char or int datatypes is that the intermediate result will be stored as an int. If the intermediate result may overflow that datatype, then the answer will be incorrect. To overcome this limitation, the letter L can be used to promote the intermediate result to a long.
When the final result of a value will be a long, using L may be insufficient to prevent overflow. In this case, append a literal with LL to promote the intermediate result to a long long and avoid overflow.

Example 14.4.2. Intermediate overflow in arithmetic containing multiplication.

For example, say an integer variable x takes on values between 0 and 1023. Consider a scenario where this variable must be multiplied by 125 and then divided by 2 to obtain a desired result. The following example (where x = 1000) demonstrates what can happen if the L promotion is not used.
\begin{align*} (125 * x) / 2 \amp= \\ (125 * 1000) / 2 \amp = \textrm{(the intermediate result overflows)}\\ (59464) / 2 \amp= 29732 \end{align*}
The following example demonstrates how to solve this issue using the L promotion is used.
\begin{align*} (125\texttt{L} * x) / 2 \amp= \\ (125\texttt{L} * 1000) / 2 \amp =\\ (125000) / 2 \amp= 62500 \end{align*}

Subsection 14.4.3 Modulo

The modulo operation (%) calculates the remainder of a variable or value after performing division with some number. Note that modulo is not defined for negative numbers! Therefore, care should be taken in code to ensure that the modulo of a negative number is not calculated.