Skip to main content

Integers

In Rust, integers are primitive types used to represent whole numbers.

  • Signed integers (i) can store both positive and negative numbers. The sign takes one bit, so the range of values is reduced compared to unsigned integers of the same size.

  • Unsigned integers (u) can store only non-negative numbers, allowing them to represent a larger range of positive numbers than their signed counterparts.

Integer Types and Their Sizes

TypeSizeRange
i88-bit-128 to 127
u88-bit0 to 255
i1616-bit-32,768 to 32,767
u1616-bit0 to 65,535
i3232-bit-2,147,483,648 to 2,147,483,647
u3232-bit0 to 4,294,967,295
i6464-bit-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
u6464-bit0 to 18,446,744,073,709,551,615
i128128-bitHuuuuugeee
u128128-bitHuuuge aswell
isizeArchitecture-dependentVaries based on CPU architecture (32 or 64-bit)
usizeArchitecture-dependentVaries based on CPU architecture (32 or 64-bit)

The isize and usize types depend on the system’s architecture. On a 32-bit system, they are 32 bits wide, and on a 64-bit system, they are 64 bits wide.

Creating and Using Integers

You can create integers using literals. By default, Rust infers i32 if no specific type is provided.

let signed: i32 = -42;
let unsigned: u32 = 42;

You can specify integer literals using suffixes:

let small = 120i8;
let large: u64 = 1_000_000;

Note: The _ is used for readability and does not affect the value.

Arithmetic Operations

Rust supports standard arithmetic operations on integers, including addition (+), subtraction (-), multiplication (*), division (/), and modulus (%):

let sum = 5 + 10;
let product = 4 * 6;
let quotient = 10 / 2;
let remainder = 10 % 3;

Overflow Handling

By default, Rust checks for overflow in debug mode. For example, if you try to assign a value that exceeds the range of the integer type, it will panic in debug mode.

In release mode, Rust allows overflow with wrapping behavior (modulo behavior). You can also use methods like .wrapping_add(), .checked_add(), .saturating_add(), and .overflowing_add() to handle overflows explicitly.

let result = 255u8.wrapping_add(1); // wraps to 0

Conversion Between Integer Types

If you need to convert between integer types, you can use as for casting:

let small: u8 = 100;
let large: u32 = small as u32;

Rust will not automatically convert between different integer types to ensure type safety.

Common Methods

Rust’s integer types come with useful methods:

  • Checking even/odd:

    let num: i32 = 4;
    println!("{}", num.is_even()); // true
    println!("{}", num.is_odd()); // false
  • Converting to/from Strings:

    let num_str = 42.to_string();
    let parsed_num: i32 = "42".parse().unwrap();

Example: Handling Overflow Explicitly

Let’s say you want to safely add two u8 values without panicking or wrapping:

fn safe_add(a: u8, b: u8) -> Option<u8> {
a.checked_add(b)
}

let result = safe_add(250, 10);
println!("{:?}", result); // None (would overflow)