#213 Jun 20, 2026

213. abs_diff — The Gap Between Two Numbers, No Underflow, No Overflow

Subtracting two unsigned integers to get their distance is a panic waiting to happen — and the signed (a - b).abs() workaround overflows just as quietly. abs_diff gives you the gap correctly, every time.

The reflex for “how far apart are these two numbers” is a plain subtraction. On unsigned types that underflows the moment the second value is larger:

1
2
3
4
let a: u32 = 10;
let b: u32 = 25;

let gap = a - b; // panics in debug, wraps to 4294967281 in release

So you reach for the defensive guard, branching on which side is bigger:

1
let gap = if a > b { a - b } else { b - a };

The signed version looks safer but isn’t. (a - b).abs() overflows when the two values are far apart, and i32::MIN.abs() panics outright because 2147483648 doesn’t fit in an i32.

Since Rust 1.60, every integer type has abs_diff — order-independent, branch-free, and immune to both traps:

1
2
3
4
5
let a: u32 = 10;
let b: u32 = 25;

assert_eq!(a.abs_diff(b), 15);
assert_eq!(b.abs_diff(a), 15);

On signed integers it returns the unsigned counterpart, which is what makes it total. The distance between the extremes is genuinely larger than i32::MAX, and abs_diff represents it without flinching:

1
2
assert_eq!((-5i32).abs_diff(5), 10u32);
assert_eq!(i32::MIN.abs_diff(i32::MAX), u32::MAX);

That last gap — 4294967295 — can’t be held in an i32 at all, which is exactly why (min - max).abs() was never going to work.

Any time you’re computing a difference and only care about magnitude — pixel distances, clock skew, tolerance checks, diffing counters — reach for abs_diff instead of subtracting and hoping the bigger number is on the left.

← Previous 212. slice::fill / fill_with — Reset Every Element Without the Loop Next → 214. slice::windows — Compare Consecutive Elements Without the Index Math