What precedence means
When an expression has several operators, Rust needs a rule for which one to apply first. That rule is operator precedence, and it works much like the order of operations from school mathematics. 1 + 2 * 3 is 7, not 9, because multiplication binds tighter than addition: Rust computes 2 * 3 first and then adds 1.
The order, from highest to lowest
- Parentheses are always respected: whatever is inside runs first.
- Unary minus, as in
-x. - The
asconversion, as inx as f64. *,/and%: multiplication, division and remainder.+and-: addition and subtraction.
Operators on the same level run from left to right. That is why 10 - 4 - 3 is 3, as (10 - 4) - 3, and why 6.0 / 4.0 * 3.0 divides first and multiplies second.
Rust has no exponent operator. The symbol ^ is bitwise XOR, so 2 ^ 3 is 1, not 8. To raise a number to a power, call a method: 2_i32.pow(3) for integers or 2.0_f64.powi(3) for floats.
The position of as is useful in practice. Because it binds tighter than /, 7 as f64 / 2.0 converts the 7 first and then divides, giving 3.5. You rarely need parentheses around a cast that is an operand of an arithmetic operator.
Examples
println!("{}", 1 + 2 * 3); // 7
println!("{}", 6 - 4 / 2); // 4
println!("{}", 5 * 4 - 2 / 2); // 19
In the first line, 2 * 3 is 6 and then 1 + 6 is 7. In the third, 5 * 4 is 20 and 2 / 2 is 1, so the result is 19.
Parentheses force a different order:
println!("{}", (1 + 2) * 3); // 9
println!("{}", (6 - 4) / 2); // 1
println!("{}", 5 * (4 - 2) / 2); // 5
In the last line, (4 - 2) is 2, then 5 * 2 is 10, then 10 / 2 is 5. Multiplication and division share a level, so they run left to right.
Same level, left to right
println!("{}", 6.0 / 4.0 * 3.0 + 5.0); // 9.5
Division and multiplication come before addition, and between themselves they go left to right: 6 / 4 is 1.5, times 3 is 4.5, plus 5 is 9.5. With integers the order matters even more, because each division drops its fraction: 6 / 4 * 3 is 1 * 3 = 3, while 6 / (4 * 3) is 0.
Nested parentheses
println!("{}", 6 / ((4 + 2) / 3)); // 3
Work from the innermost pair outwards. (4 + 2) is 6, then 6 / 3 is 2, and finally 6 / 2 is 3.
The exercise
The starting code prints 2 + 3 * 3. Multiplication runs first, so it computes 2 + 9 and prints 11. The goal is to print 15. To get 15 from a multiplication by 3, the first factor must be 5, which is 2 + 3. So the addition has to run first, and the way to do that is to wrap it in parentheses.
The solution in Rust
println!("{}", (2 + 3) * 3);
Now Rust evaluates (2 + 3) to 5, multiplies by 3, and prints 15.
Parentheses as documentation
You never have to memorize every level. When an expression mixes several operators and you are not sure how it reads, add parentheses. (price * 4) + bag evaluates exactly like price * 4 + bag, but nobody has to think about it. Redundant parentheses cost nothing at run time, because the compiler handles them before the program runs.
Common mistakes
- Reading left to right.
2 + 3 * 3is not(2 + 3) * 3. The result is 11, since multiplication wins. - Expecting
^to be a power. It is XOR, so2 ^ 3prints 1. - Unbalanced parentheses. Every
(needs a matching), or the program won't compile. - Parentheses in the wrong place.
2 + (3 * 3)changes nothing: it is the default order spelled out, and the output stays 11. - Negative numbers and powers.
-2_i32.pow(2)is -4, because the method call runs before the minus. Write(-2_i32).pow(2)to get 4.
Key takeaways
- Parentheses first, then
*,/,%, then+,-. - Equal-level operators run from left to right.
- Add parentheses whenever you want a different order, or just to make the intent clear.
- Rust has no power operator; use
poworpowi.
