Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/fp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

# Rust also has two primitive types for floating-point numbers, which are numbers with decimal points.
Rust’s floating-point types are f32 and f64, which are 32 bits and 64 bits in size, respectively.
The default type is f64 because on modern CPUs, it’s roughly the same speed as f32 but is capable of more precision.
# Differences Between 'f32' and 'f64' in Rust
The 64-bit floating-point type is very similar to f32, but has increased precision by using twicw as many bits
## Precision
- **`f32`**: 32 bits (4 bytes), approximately **6–7 decimal digits** of precision.
- **`f64`**: 64 bits (8 bytes), approximately **15–16 decimal digits** of precision.

## Memory Usage
- **`f32`**: 4 bytes.
- **`f64`**: 8 bytes.

## Performance
- **`f32`**: Faster for some operations and uses less memory.
- **`f64`**: More precise but slightly slower.

## Default Type
- Rust defaults to `f64` for floating-point literals unless explicitly annotated.

76 changes: 62 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
fn main() {
// intro_to_u();
string_handler();
println!(".......................................................");
type_conversion();
println!(".......................................................");
signed_integers();
println!(".......................................................");
string_conversion();
}


// function to encapsulate all integers
fn intro_to_u(){
let sum_result: u8 = sum(5, 10);
Expand Down Expand Up @@ -89,20 +96,6 @@ fn convert_to_string_v2(x: &str) -> String {
String::from(x)
}

=======
// function that encapsulate all integers
fn intro_to_u() {
// subtract
// multiplication
// division
let sum_result: u8 = sum(5, 10);
println!("the sum result is: {}", sum_result);
}

fn sum(x: u8, y: u8) -> u8 {
x + y // implicit return
// return x + y; // explicit return
}

// handle all string-related functions
fn string_handler() {
Expand All @@ -125,5 +118,60 @@ fn intro_to_ownable_string() {
println!("ptr = address in heap memory: {:?}", name.as_ptr());
}

fn type_conversion(){
let sum_casting: u32 = sum_cast(50, 50);
println!("The sum of the two values is {}", sum_casting);
let product_casting: u8 = multiply_cast(10, 15);
println!("The product of the two values is {}", product_casting);
}

// Type casting 1
fn sum_cast(x: u8, y: u8) -> u32 {
let result = x + y;
result as u32
}

// Type casting 2
fn multiply_cast(p: u32, q: u32) -> u8 {
let answer = p * q;
answer as u8
}

fn signed_integers(){
let signed_sum: i8 = sum_signed(19, 19);
let signed_subtraction: i8 = substract_signed(100, 50);
let signed_multiplication: i8 = multiply_signed(10, 12);
let signed_division: f32 = divide_signed(100, 18);
println!("The sum of the two values is {}", signed_sum);
println!("The difference between the two values is {}", signed_subtraction);
println!("The product of the two values is {}", signed_multiplication);
println!("The division of the two values is {}", signed_division);

}

fn sum_signed(a: i8, b: i8)-> i8{
a + b
}
fn substract_signed(a: i32, b:i32)-> i8{
return (a-b)as i8;
}
fn multiply_signed(a: i8, b: i8)-> i8{
a * b
}
fn divide_signed(a: i64, b: i64)-> f32{
return a as f32 / b as f32;
}

fn string_to_str(input: &String) -> &str{
input.as_str()
}

fn string_conversion(){
let string_input = String::from("My name is Wisdom Enyinnaya");
let referenced_string = string_to_str(&string_input);

println!("String: {}", string_input);
println!("&str: {}", referenced_string);
}


42 changes: 42 additions & 0 deletions src/pointer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

# Rust Smart Pointers

In Rust, pointers are variables that hold an address in memory, which refers to or "points at" other data. There are two primary types of pointers in Rust: **references** and **smart pointers**.

## References

A **reference** is the most common type of pointer in Rust. It is indicated by the `&` symbol and borrows the value it points to. References are lightweight pointers with no special capabilities other than referring to data. They have no overhead and are a fundamental part of Rust's ownership and borrowing system.

## Smart Pointers

A **smart pointer** is a data structure that acts like a pointer but also includes additional metadata and capabilities. Smart pointers originated in C++ and have been implemented in various languages, including Rust.

While references only borrow data, **smart pointers often own the data** they point to, which is a key distinction in Rust. Smart pointers are implemented using structs and implement the `Deref` and `Drop` traits to provide extra functionality. These traits make smart pointers behave like references and allow for custom code when an instance of the smart pointer goes out of scope.

### Common Smart Pointers in Rust

Rust provides several smart pointer types in the standard library:

1. **`Box<T>`**: A smart pointer for allocating values on the heap. It allows you to store values on the heap and provides ownership semantics.
2. **`Rc<T>`**: A reference-counted smart pointer that allows multiple ownership of the same data. It keeps track of the number of owners and cleans up the data when there are no remaining owners.
3. **`Ref<T>` and `RefMut<T>`**: These smart pointers are used with `RefCell<T>`, a type that enforces borrowing rules at runtime instead of compile time. They enable interior mutability, allowing data to be mutated even if the `RefCell<T>` itself is immutable.
4. **`String` and `Vec<T>`**: These types were encountered earlier in the book, and although they weren’t explicitly called smart pointers, they fit the definition. They own memory, provide metadata, and have additional capabilities, like ensuring data is valid UTF-8.

### Traits: `Deref` and `Drop`

Smart pointers in Rust implement two key traits:

- **`Deref`**: This trait allows an instance of the smart pointer to behave like a reference, meaning you can use smart pointers in places where a reference would normally be used.
- **`Drop`**: This trait allows you to define custom logic that runs when the smart pointer goes out of scope. It is used to manage memory and other cleanup tasks.

### Ownership and Borrowing

Smart pointers are an essential part of Rust’s ownership and borrowing model. While references simply borrow data, smart pointers often own the data they point to, which means they have the responsibility of cleaning up that data when it's no longer needed. This helps ensure that memory is managed safely and efficiently.

### Interior Mutability Pattern

Rust also introduces the concept of **interior mutability**, where an immutable type can expose an API to mutate its internal data. This is primarily used with types like `RefCell<T>`, which allows for runtime checks of borrowing rules.

### Reference Cycles and Memory Leaks

One of the challenges with smart pointers is dealing with **reference cycles**, where two or more smart pointers reference each other in a loop. This can result in memory leaks because the reference count never drops to zero.