Arithmetic Operations and Type Conversions
C++ performs all meaningful conversions between basic types in assignments and arithmetic operations, so they can be mixed freely.
Why Mixing Doubles and Integers Looks Suspicious
Suppose you have a floating-point variable and a whole-number variable sitting side by side in the same arithmetic expression. A natural first reaction is suspicion. It can seem that the language should refuse the combination, or that the result must somehow be wrong. C++ does not work that way. In assignments and in arithmetic operations, C++ performs all meaningful conversions between the basic types so that they can be mixed freely.
What do you think happens?
Suppose d is a double and i is an int. When you write the addition d + i, in which type is the addition carried out?
Reveal answer
double
The addition is carried out in double precision. The common type is decided by the operands in the expression, which here means the int operand is converted to double so that both operands share the type that keeps the highest precision. Where the result is stored is a separate step, covered in a later section.
Commit to your answer before reading on. The reason the answer is what it is will matter for every conversion rule that follows, because the rule is about the operands, not about any variable waiting to receive the result.
Tracing a Mixed-Type Expression
The conversions that C++ applies to operands in an expression are called the usual arithmetic conversions. Their purpose is stated plainly: they aim to ensure that expressions are computed at the highest precision of their operands. Each operand is considered, and the operands are brought to a common type that keeps the most precision among them. The conversion is applied to the operands so the operation can proceed in that common type.
Read the tree from the top down. The double operand stays as it is, while the int operand is converted so both operands share the double type. The addition then happens in double precision, and the result is a double. This gives you a chain of reasoning to repeat whenever you meet a mixed-type expression: identify the operand types, find the common type that keeps the highest precision, and follow the operation in that type.
Predicting the computation type of 3 * 2.5 + 1
Evaluate the expression 3 * 2.5 + 1 and state the type in which each subexpression is computed.
- 1Step 1: Identify the operand types
The literal 3 is an int, the literal 2.5 is a double, and the literal 1 is an int.
- 2Step 2: Evaluate 3 * 2.5
The operands are of different types, so the usual arithmetic conversions bring them to the common type that keeps the most precision, which is double. The int 3 becomes 3.0, and the multiplication yields the double 7.5.
- 3Step 3: Evaluate 7.5 + 1
The left operand is already a double and the int 1 is converted to 1.0. The addition is carried out in double precision.
- 4Step 4: Read the final type
The whole expression is computed as a double with the value 8.5.
The expression is computed in double precision and its value is 8.5. Each subexpression takes the type of the common type its operands were brought to.
Computation Type Versus Storage Type
Computing in a common type is only half of the story. The result of an expression is then assigned to a variable, and that variable has its own type. The type of the computation and the type of the storage are separate. When the destination type is less precise than the computed value, the value changes on the way in.
5.5
7- d + i is computed in double because i is converted to double
- d * i produces the double value 7.5 during the computation
- Assigning 7.5 to the int variable stored discards the fractional part, leaving 7
Truncation means the fractional part is discarded. The stored value is not rounded in this description; the source states that assigning the product to an int variable truncates the double value to an int. Notice that the value 7 is stored, even though the computation itself was correct in double precision.
Assignment Versus Equality, Step by Step
A second belief causes real bugs: that the single equals sign asks a question about two values. It does not. In C++ the single equals sign = is the assignment operator. It assigns a value to a variable. The expression on the right is evaluated, and the result is stored in the variable on the left. The double equals sign == is the equality test, which compares two values and produces a true or false result.
5
1
5- x = 5 stores 5 in x and changes the variable
- x == 5 compares the two values and prints 1, which represents true
- After the comparison, x still holds 5 because == does not assign
The misconception to watch for is reading a line such as d = d + i as a statement of fact, something like d is equal to d plus i. Read it as an instruction instead: evaluate d + i, then store the result in d. Under that reading the line makes sense, and it changes d.
Mistakes Beginners Make with = and ==
Common mistake Writing a single = when a comparison was intended
What it looks likeif (x = 5) ...Why it failsThe single equals sign assigns 5 to x rather than testing whether x equals 5. The condition is then evaluated on the assigned value, and x has been changed.
Do this insteadUse the double equals sign for the test: if (x == 5) ...
Common mistake Assuming the result type is decided by the destination variable
What it looks likeExpecting d + i to be computed as int because the result will be stored in an int
Why it failsThe usual arithmetic conversions choose the common type from the operands. The destination type only matters when the computed value is assigned.
Do this insteadIdentify the operand types first to find the computation type, then consider the storage type separately.
Common mistake Expecting a fractional value to survive assignment to an int
What it looks likeint stored = d * i; with d * i equal to 7.5Why it failsAssigning a double to an int truncates the fractional part, so the stored value is 7.
Do this insteadChoose a destination type that can hold the precision you need, or accept the truncation deliberately.
Common mistake Choosing the wrong operator usually does not produce a compile error, so the mistake can persist unnoticed
Checking Your Understanding
Given double x = 9.0 and int n = 4, which type is the expression x / n computed in, and what value does it produce? Then state what happens if the result is assigned to an int variable.
Hints
- Look only at the operand types of x / n to find the computation type.
- The int 4 is converted to double, so the division is carried out in double precision.
- Assigning a double to an int truncates the fractional part of the stored value.
Key Takeaways
- C++ performs the usual arithmetic conversions so that basic types such as double and int can be mixed in one expression.
- An expression is computed at the highest precision of its operands, so a double combined with an int is computed in double-precision arithmetic.
- The computation type and the storage type are separate: assigning a double to an int truncates the fractional part.
- The single equals sign = assigns a value to a variable, while the double equals sign == tests whether two values are equal without changing them.