Concepts / Arithmetic Operations and Type Conversions

Arithmetic Operations and Type Conversions

C++ performs all meaningful conversions between basic types in assignments and arithmetic operations, so they can be mixed freely.

  • Programming

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?

  • int

  • double

  • It depends on the type of the variable the result is stored in

Reveal answer
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.

d + id: doubleno change neededdouble sumcomputed in doubleprecisioni: intconverted to doublei as doubleleft operandright operandconvertcommon type doublecommon type double
Where each operand is converted and what type the addition is carried out in. The double operand needs no change, the int operand is converted to double, and the sum is a double.

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.

Worked example

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.

  1. 1
    Step 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.

  2. 2
    Step 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.

  3. 3
    Step 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.

  4. 4
    Step 4: Read the final type

    The whole expression is computed as a double with the value 8.5.

Result

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.

cpp
Output
5.5
7
Notes on the code
  • 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
d * idouble result7.5double valuestoredint variable7fraction discardedevaluates totruncated on assignment to intholds
The product d * i is a double value of 7.5 before assignment. After it is stored in an int, the fractional part is discarded and the variable holds 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.

x = 5assignment operatorx now holds 5variable changesx == 5equality testtrue or falsex is unchangedstores valueproduces result
Two operators that look almost identical do different things. The assignment changes the variable on the left, while the equality test only reports whether two values match.
cpp
Output
5
1
5
Notes on the code
  • 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 like
    if (x = 5) ...
    Why it fails

    The 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 instead

    Use 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 like

    Expecting d + i to be computed as int because the result will be stored in an int

    Why it fails

    The usual arithmetic conversions choose the common type from the operands. The destination type only matters when the computed value is assigned.

    Do this instead

    Identify 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 like
    int stored = d * i; with d * i equal to 7.5
    Why it fails

    Assigning a double to an int truncates the fractional part, so the stored value is 7.

    Do this instead

    Choose 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

MEDIUM

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.

Related concepts

More concepts starting with A