5.7 Numeric Literals
Each numeric literal in Rust must have a well-defined type at compile time, decided by context or by an explicit suffix.
5.7.1 Integer Literals
By default, integer literals are i32. You can add a type suffix (like 123u16) to specify another type. Underscores (_) are allowed within numeric literals for readability:
#![allow(unused)] fn main() { let large = 1_000_000; // 1 million, i32 }
5.7.2 Floating-Point Literals
By default, floating-point literals are f64. To specify f32, you can add a suffix like 3.14f32. Rust requires at least one digit before the decimal point (0.7 is valid, while .7 is not), but you can write a trailing decimal point with no digits after it (1. is equivalent to 1.0).
5.7.3 Hex, Octal, and Binary
Rust supports integer literals in multiple bases: hexadecimal (0x), octal (0o), and binary (0b). Although decimal and hexadecimal are most common, octal can be handy for file permissions in Unix-like systems or certain hardware. You can also create a byte literal with b'X', yielding a u8 for the ASCII code of X.
fn main() { let hex = 0xFF; // 255 in decimal let oct = 0o377; // 255 in decimal let bin = 0b1111_1111; // 255 in decimal let byte = b'A'; // 65 in decimal (ASCII for 'A') println!("{} {} {} {}", hex, oct, bin, byte); }
5.7.4 Type Inference
Rust infers numeric types by how they are used. For example:
fn main() { let array = [10, 20, 30]; let mut i = 0; // The literal '0' could be multiple integer types while i < array.len() { println!("{}", array[i]); i += 1; } }
Since i is compared to array.len() (which returns usize) and used to index the array (also requiring usize), the compiler infers i to be usize. Thus, Rust often spares you from writing explicit type annotations. However, if there is not enough information to determine a single valid type, you must provide a hint or cast.