Use n % 2 != 0 for i64 parity. A Result-returning parser preserves the difference between invalid input and an even integer.
For a Rust integer, n % 2 != 0 is a clear odd-number test. An i64 parameter gives the function a concrete signed range, while a separate parser can return a useful error when external text does not fit that range.
Return parsing errors with Result
use std::num::ParseIntError;
fn is_odd(n: i64) -> bool {
n % 2 != 0
}
fn parse_odd(text: &str) -> Result<bool, ParseIntError> {
text.parse::<i64>().map(is_odd)
}
fn main() {
match parse_odd("-117") {
Ok(odd) => println!("odd: {odd}"),
Err(error) => eprintln!("invalid integer: {error}"),
}
}
Keep parser policy explicit
map calls is_odd only when parsing succeeds. A failed parse stays an error, while Ok(false) is the valid answer for an even integer. Keeping those outcomes separate matters when a command-line argument or uploaded record contains a typo.
The standard library's i64 parsing documentation describes the decimal format and its errors. This example does not trim input. If a user interface should permit surrounding whitespace, call trim visibly at the boundary. Do not conceal that policy inside an arithmetic predicate.
Test negative values and boundaries
Rust uses a remainder based on division that truncates toward zero. A negative odd dividend therefore has a remainder of negative one when divided by two. The operator reference defines the behavior. Comparing the result with zero works for either sign; comparing with positive one does not.
These checks cover both the arithmetic and the parser contract:
assert!(is_odd(-117));
assert!(!is_odd(-116));
assert!(!is_odd(0));
assert!(!is_odd(i64::MIN));
assert!(is_odd(i64::MAX));
assert!(parse_odd("117.5").is_err());
assert!(parse_odd(" 117 ").is_err());
assert!(parse_odd("9223372036854775808").is_err());
The implementation does not call abs, negate the number, or increment it. That avoids introducing extra operations at the signed minimum and maximum. Rust has overflow rules for certain arithmetic operations, including dividing or taking the remainder of the signed minimum by negative one. The constant divisor two in this helper does not trigger that case.
Match the integer type to the domain
Use the integer type that matches the domain. usize is appropriate for local collection indexes, while an explicitly sized type is easier to align with a file format. A generic parity abstraction is usually unnecessary when the application has one well-defined representation.
Do not cast a floating-point reading into an integer merely to make this function accept it. That would answer a question about the converted value instead of validating the original measurement. Make rounding or rejection an explicit earlier step. Likewise, avoid unwrap on untrusted text unless a panic is genuinely the intended input-error behavior.
For an unsigned counter, the same expression works in a helper taking u64. Keep that as a separate, explicit signature when negative values are forbidden by the data model.