Start learning free

LESSON 130 OF 414 · WHILE LOOPS & FOR LOOPS

Printing Odd Numbers in Rust: for Loops with step_by

Practice Read the full explanation

Let's see an example where we change the step.

We can print all even numbers from 2 through 10:

for i in (2..=10).step_by(2) {
	println!("{}", i);
}

The output of this code is:

2
4
6
8
10

Let's break down this code:

  • The range starts at 2, so we start iterating from number 2.

  • The range end is 10 (inclusive with ..=), so we end at number 10. We could've written (2..11).step_by(2) and it would still be correct.

  • The step is 2 via step_by(2), so we increase our number by 2 every time.


Assignment

Let's print all odd numbers from 7 through 23 using a for loop.


Hint
Look at the examples above if you get stuck.


STEP 1 OF 2
    Ctrl + Enter to check

    RUST · WHILE LOOPS & FOR LOOPS

    Printing Numbers 4 in Rust, explained

    Problem overview

    The task is to print all the odd numbers from 7 through 23, one per line, with a for loop. The expected output is 7, 9, 11, 13, 15, 17, 19, 21 and 23.

    The previous lesson printed consecutive numbers, where the loop variable increases by 1. Here the numbers are two apart, so the range has to take bigger steps.

    Approach: a range with a step

    A plain Rust range always moves by 1, and it has no step setting in its syntax. To change the step, you call the method step_by on the range. It returns a new iterator that takes every n-th value of the original.

    for i in (2..=10).step_by(2) {
        println!("{}", i);
    }

    This prints 2, 4, 6, 8 and 10. The range 2..=10 holds the nine numbers from 2 to 10, and step_by(2) keeps the first and then every second one after it: 2, 4, 6, 8, 10.

    Two things follow from that description:

    • The sequence always starts with the range's first value. So the start of the range decides whether you get odd or even numbers. Starting from 7 and stepping by 2 gives odd numbers, so no if inside the loop is needed.
    • The sequence stops at the end of the range. If the step jumps past the end, the loop stops. Using (2..11).step_by(2) gives the same numbers as (2..=10).step_by(2).

    Step by step

    1. Build the range 7..=23. It starts at the first odd number to print, 7, and includes 23, the last one.
    2. Put it in parentheses and call .step_by(2) on it. The parentheses matter, as explained below.
    3. Loop over the result with for i in ..., so i takes the values 7, 9, 11, ..., 23.
    4. Print i with println!("{}", i);. The {} is a placeholder for the value, and each call ends the line.

    The solution in Rust

    for i in (7..=23).step_by(2) {
        println!("{}", i);
    }

    Details a learner might trip on:

    • Why the parentheses. A method call binds tighter than the range operator. Without parentheses, 7..=23.step_by(2) tries to call step_by on the number 23, and the compiler reports can't call method step_by on type {integer}. It even suggests surrounding the range in parentheses.
    • The step is a count, not an end. The argument 2 means "take every second value". It is a usize, and it cannot be 0: step_by(0) panics with assertion failed: step != 0.
    • The loop variable has type i32 here, which is Rust's default for whole numbers.

    The step count is easy to predict. The values are 7, 9, ..., 23, and the number of passes is (23 - 7) / 2 + 1 = 9.

    An alternative you may meet

    You could loop over every number from 7 through 23 and print only the odd ones with an if and the remainder operator, if i % 2 == 1. It prints the same nine numbers, but it makes 17 passes where 9 are needed, and the condition is one more thing to get wrong. With step_by, the odd numbers come straight from the start and the step.

    Edge cases and common mistakes

    • Starting at the wrong number. (6..=23).step_by(2) gives 6, 8, ..., 22, which are even. The start decides the parity.
    • Missing the last value. (7..23).step_by(2) stops at 21, because 23 is excluded.
    • Forgetting the parentheses, which is a compile error.
    • Using a step of 0, which panics at run time.
    • Thinking the step is the end. step_by(2) does not limit the loop to two passes.

    Testing

    • (7..=23).step_by(2) prints 7, 9, 11, 13, 15, 17, 19, 21, 23.
    • (2..=10).step_by(2) prints 2, 4, 6, 8, 10.
    • (0..10).step_by(3) prints 0, 3, 6, 9.
    • (5..=5).step_by(2) prints 5 only.
    Keep going with RustAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free