Exploring Rust Data Types: A Comprehensive Guide for Developers

We can use data types in Rust to condition the type of data associated with the variables. For example-

let alphabet: char;

Above, char is the data type that mark that the alphabet variable be able only store the character data.

Data Types in Rust Program :

Follow the four primary data types in Rust program also known as scalar types:

  1. Integer
  2. Floating-Point
  3. Boolean
  4. Character
  5. Compound

1. Integer Type :

In Rust, we can use integer data types to store full numbers. For example :

let number: i32 = 200;

Here, we have maked the number of variable type i32 (integer) and stored the value 200.

Integer type i32 has get two parts to it:

  1. i - determine signed integer type (can store all positive or negative value)
  2. 32 - size of the data type (receives 32 bits of space in storage)

Signed Integer Type in Rust Programming :

fn main() {
    // Signed integer type 
    let x: i32 = -200;
    let y: i32 = 200;

    println!("x = {}", x);
    println!("y = {}", y);
}

Output :

x = -200
y = 200

Here, you have defined two integers x and y with values -200 and 200 gradually and printed it on the screen.

Unsigned Integer Type In Rust :

We can also make variables which can only store positive integer values. For example-

fn main() {
    // Unsigned integer type
    let x: u32 = 300;

    println!("x = {}", x);
}

Output :

x = 300

Above, u32 mark that the x variable only store positive values. u mark unsigned integer type.

If you push to store negative numbers to u32 type variables, you will get an error. For example-

fn main() {
    let x: u32 = -200;

    println!("x = {}", x);
}

Error:

error[E0600]: cannot apply unary operator `-` to type `u32`
 --> main.rs:2:18
  |
2 |   let x: u32 = -200;
  |                ^^^^ cannot apply unary operator `-`
  |
  = note: unsigned values cannot be negated

Integer Data Types of Categories in Rust :

Depend on the size of data, you can what is more classify the signed and unsigned integer type into various categories :-

+-------+--------+----------+
| Size  | Signed | Unsigned |
+-------+--------+----------+
|  8-bit |   i8   |    u8    |
| 16-bit |  i16   |   u16    |
| 32-bit |  i32   |   u32    |
| 64-bit |  i64   |   u64    |
|128-bit | i128   |   u128   |
+-------+--------+----------+

2. Floating Point Type In Rust :

Floating point types are maked to store fractionary numbers (numbers with decimal points). In Rust Program, floating-point data types can be used divided into:

  1. f32
  2. f64

Above, the f character represents a floating point number also32 and 64 represent the size in bits.

Let’s create a look at an example-

Let's take a look at an example,

See, f32 is a type of declaration for the floating point value. In this policy, x is assigned to a floating point value of 3.1.

Examples

Example 1: Basic Usage of f32 and f64 In Rust

fn main() {
    // Using f32
    let my_float_32: f32 = 3.14;
    println!("f32: {}", my_float_32);

    // Using f64
    let my_float_64: f64 = 3.141592653589793;
    println!("f64: {}", my_float_64);

    // Rust infers type
    let inferred_float = 2.71828; // Inferred as f64
    println!("Inferred: {}", inferred_float);
}

Example 1 Output :

f32: 3.14
f64: 3.141592653589793
Inferred: 2.71828

Example 2: Performing Arithmetic Operations In Rust

fn main() {
    let x: f32 = 5.0;
    let y: f32 = 2.0;

    // Addition
    let sum = x + y;
    println!("Sum: {}", sum);

    // Subtraction
    let difference = x - y;
    println!("Difference: {}", difference);

    // Multiplication
    let product = x * y;
    println!("Product: {}", product);

    // Division
    let quotient = x / y;
    println!("Quotient: {}", quotient);
}

Example 2 Output :

Sum: 7
Difference: 3
Product: 10
Quotient: 2.5

Example 3: Precision Issues and Comparison In Rust

fn main() {
    // Floating-point precision issue
    let result = 0.1 + 0.2;
    println!("Sum: {}", result); // May not be exactly 0.3 due to precision

    // Comparison with epsilon for precision
    let epsilon = 1e-10;
    let sum = 0.1 + 0.2;
    let result = (sum - 0.3).abs() < epsilon;
    println!("Is close to 0.3? {}", result); // Should be true if close enough
}

Example 3 Output :

Sum: 0.30000000000000004
Is close to 0.3? true

Here, output for the sum (0.30000000000000004) interpret the floating-point legibility issue that arises due to the nature of binary representation. But, when checking if the sum is close sufficient to 0.3 within the specified epsilon value (1e-10), the result is true, initiative that it’s considered close enough for practical purposes.

3. Boolean Type In Rust :

In Rust Program, a boolean data type have two possible values: true otherwise false. For example:-

// boolean value true
let flag1: bool = true;

// boolean value false
let flag2: bool = false;

Here, you have used the bool word to represent the boolean type in Rust Program.

Example: Boolean Type In Rust

fn main() {
    // boolean type
    let flag1: bool = true;
    let flag2: bool = false;

    println!("flag1 = {}", flag1);
    println!("flag2 = {}", flag2);
}

Boolean Type In Rust Example Output :

flag1 = true
flag2 = false

4. Character Type In Rust :

In Rust, we can define custom data types using structs and enums. below see an example of defining a simple character type using a struct:

// Define a custom character type using a struct
struct CustomChar {
    character: char,
    // You can add more fields if needed
}

fn main() {
    // Create an instance of CustomChar
    let my_char = CustomChar { character: 'A' };

    // Access the fields of the struct
    println!("My custom character: {}", my_char.character);
}

Output :

My custom character: A

Explanation:

  1. A custom character types (CustomChar) is defined by using a struct with a single field (character).
2. An example of `CustomChar` is created of the character 'A'.

3. The `println!` macro is maked to print the value of the character field within the struct example.

If we want to illustrate different types of characters, we can use enums. below give an example:

// Define a custom character type using an enum
enum CustomChar {
    Alphabetic(char),
    Numeric(i32),
    Special(char),
}

fn main() {
    // Create instances of CustomChar using different variants
    let alphabetic_char = CustomChar::Alphabetic('A');
    let numeric_char = CustomChar::Numeric(7);
    let special_char = CustomChar::Special('@');

    // Match on the enum variants to access the values
    match alphabetic_char {
        CustomChar::Alphabetic(c) => println!("Alphabetic character: {}", c),
        _ => unreachable!(),
    }

    match numeric_char {
        CustomChar::Numeric(n) => println!("Numeric character: {}", n),
        _ => unreachable!(),
    }

    match special_char {
        CustomChar::Special(c) => println!("Special character: {}", c),
        _ => unreachable!(),
    }
}

Output :

Alphabetic character: A
Numeric character: 7
Special character: @

Explanation:

  1. A custom character type (CustomChar) is defined by using an enum with three variants:- Alphabetic, Numeric, and Special. Every variant can hold several types of values associated with it. 2. Instances of CustomChar are created by using several variants (Alphabetic, Numeric, and Special) with specific values. 3. The match statement is used to pattern match on the of enum variants and essence the values. The program after prints the extracted values depend on the matched variants.

Inference Type in Rust :

So far away, we have alluded the data type during the variable declaration. Only, in Rust we can make variables without mentioning a data type. For example-

let x = 51;

In this case, Rust Program automatically defines the data type by watching at the value of the variable x and associates it with variable. This method is known as Type Inference.

So, lets see an example-

fn main() {
    let x = 51;

    println!("x = {}", x);
}

Example Output :

x = 51

Above example, we can see that we haven’t mentioned the data type of x variable. Because it is Rust will automatically set i32 as the type (default type for integer variable) by watching at the value 51.

5. Compound Data Types in Rust :

In Rust Program, compound data types attach multiple values into one data structure. The basic compound data types are tuples, arrays, structs, and enums. Here’s an examples:

(i) Tuples :

Tuples Compound are ordered collections of elements with several data types. They have a permanent size, and their elements accessed by index.

// Tuple with elements of different types
let person: (String, i32, char) = ("Alice".to_string(), 30, 'F');

// Accessing elements
let name = person.0;
let age = person.1;
let gender = person.2;

(ii) Arrays :

Arrays are permanent-size collections of elements with the same data type. different tuples, all elements must have the same type, and arrays are allocate on the stack

// Array of integers
let numbers: [i32; 3] = [1, 2, 3];

// Accessing elements
let first = numbers[0];
let second = numbers[1];
let third = numbers[2];

(iii) Structs :

Structs make allowance for you to define your own data types by grouping related fields together. They provide a way to make more complex data structures.

// Define a struct
struct Person {
    name: String,
    age: i32,
    gender: char,
}

// Create an instance of the struct
let alice = Person {
    name: "Alice".to_string(),
    age: 30,
    gender: 'F',
};

// Accessing fields
let name = alice.name;
let age = alice.age;
let gender = alice.gender;

(iv) Enums :

Enums make allowance for you to define a type by enumerating its possible values. Every value have associated data, allowing for more flexibility.

// Define an enum
enum Gender {
    Male,
    Female,
    Other,
}

// Define a struct with an enum field
struct Person {
    name: String,
    age: i32,
    gender: Gender,
}

// Create an instance of the struct
let alice = Person {
    name: "Alice".to_string(),
    age: 30,
    gender: Gender::Female,
};

Enums can also have connected data:

// Enum with associated data
enum Measurement {
    Weight(f64),
    Height(i32),
}

// Examples
let weight = Measurement::Weight(70.5);
let height = Measurement::Height(170);

Above compound data types in Rust Program provide a powerful and flexible way to structure in your data.

Previous
A Guide To Variables and Mutability In Rust Programming
Next
Rust Type Casting: A Comprehensive Guide for Efficient Programming