Problem overview
The function abs_diff takes two i32 values, a and b, and returns the distance between them on the number line. That is a - b or b - a, whichever is not negative. The order of the arguments doesn't matter: abs_diff(3, 0) and abs_diff(0, 3) are both 3.
Worked examples: abs_diff(10, -1) is 11, abs_diff(-5, -7) is 2 and abs_diff(6, -6) is 12. The lesson asks you to write this with a comparison instead of calling the library's absolute-value function.
Approach
Subtracting the smaller number from the larger one always gives a result that is zero or positive. So find out which of the two is smaller and subtract in that order. If a is less than b, the answer is b - a. Otherwise a is greater than or equal to b, and the answer is a - b. When the numbers are equal, either order gives 0.
Trace abs_diff(-5, -7). Here a is -5 and b is -7. Since -5 is not less than -7, the if is skipped and the function returns -5 - (-7), which is 2. Now swap the arguments: abs_diff(-7, -5) takes the if branch and returns -5 - (-7) as well. Both orders end in the same subtraction, with the larger number first.
The absolute difference is the absolute value of a - b, and the comparison does the sign-flipping work that an abs function would otherwise do.
Step by step
- Compare the inputs. Write an
ifwith the conditiona < b. Rust doesn't need parentheses around it, but the braces are required. - Handle the case where
ais smaller. Inside theif,return b - a;. Subtracting the smaller number from the larger one can't be negative. - Handle the rest below the
if. Addreturn a - b;after it. Noelseis needed: whena < bis true the function has already returned, so this line only runs whenais greater than or equal tob.
The solution in Rust
impl Solution {
fn abs_diff(a: i32, b: i32) -> i32 {
if a < b {
return b - a;
}
return a - b;
}
}
Rust details worth knowing:
- Early return replaces
else. Areturnends the function immediately, so code after anifthat returns only runs when the condition was false. The lines read as "if a is smaller do this, otherwise do that" without the extra block. - The same logic as an expression. Since
if/elseproduces a value in Rust, the body can also beif a < b { b - a } else { a - b }with noreturnand no semicolon. - A built-in exists. Integer types have an
abs_diffmethod, as in7i32.abs_diff(-3), which gives10. Fori32it returns au32, so it avoids the overflow described below. The lesson's function is an associated function ofSolution, called asSolution::abs_diff(a, b), so the two don't conflict. - Same type in and out. The parameters and the result are all
i32, so Rust does no conversion between them.
Edge cases and common mistakes
- Equal numbers. With
a == bthe condition is false and the function returnsa - b, which is0. Usinga <= binstead would also work. - Negative inputs.
abs_diff(-5, -7)compares-5 < -7, which is false, and returns-5 - (-7), which is2. Subtracting a negative number adds its size. - Subtracting in a fixed order. Always returning
a - bgives-3forabs_diff(0, 3). The comparison is what keeps the result non-negative. - Overflow. The difference of two
i32values can be larger than ani32can hold. In the optimized build the lessons use,abs_diff(i32::MAX, -1)wraps silently and returns-2147483648. A debug build panics on the same subtraction. Ordinary inputs stay far from the limit. - Missing return. If the last line of the function is
a - b;with a semicolon, the function ends without a value and the compiler reports mismatched types. Writereturn a - b;, or drop the semicolon to make it the final expression.
Testing
a = 3,b = 0gives3.a = 0,b = 3gives3.a = 10,b = -1gives11.a = -5,b = -7gives2.a = 6,b = -6gives12.
