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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2021"

[dependencies]

151 changes: 149 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,149 @@
# Rust Sessions
Intro to primitives
1. Difference Between fp32 and fp64 Data Types
In Rust, floating-point numbers can be represented by two types

f32: 32-bit floating-point number
f64: 64-bit floating-point number
Key Differences
Bit Size:
f32 uses 32 bits to represent a number.
f64 uses 64 bits, which allows for more precision and a larger range.

Precision:
f32 gives you approximately 7 decimal digits of precision.
f64 gives you approximately 15-16 decimal digits of precision

f32 = 1.1234567; // 7 decimal places, limited precision
f64 = 1.1234567891234567; // 15-16 decimal places, high precision


Range:
f32 can represent numbers between 1.4 x 10^-45 to 3.4 x 10^38.
f64 can represent numbers between 5.0 x 10^-324 to 1.8 x 10^308

Memory Usage:
f32 uses less memory (4 bytes).
f64 uses double the memory (8 bytes).

When to Use:
we can use f32 when performance and memory efficiency are important and precision isn’t critical (e.g., graphics, gaming, some ML models).
we can use f64 when higher precision or a larger range is needed (e.g., scientific computations, financial calculations).


2. Role of Pointers in Memory Management in Rust
In Rust, pointers are crucial for memory management, but unlike languages like C or C++, Rust provides safe memory management through its ownership model, ensuring that most pointer issues (like dangling pointers, null pointers, etc.) are handled at compile-time.

Key Points About Pointers in Rust


Memory Address:
In Rust, pointers store the memory address of a variable. These are like references to variables stored elsewhere in memory, allowing you to directly manipulate the data.

let x = 10;
let y = &x; // `y` is a pointer to `x`
println!("The value of x is: {}", x); // Accessing value of `x` directly

Dynamic Memory Allocation:
Rust automatically manages dynamic memory through its ownership model, but can be manually allocate using Box<T>, Rc<T> (reference-counted), and Arc<T> (atomic reference-counted) for heap-allocated data.

Efficient Data Access:
By using references (essentially pointers) in Rust, data can be passed around efficiently without being copied.
let s = String::from("Hello");
let t = &s; // Borrowing a reference to `s`
println!("{}", t); // Access data without copying

Pass-by-Reference:
Rust uses references (&T) and mutable references (&mut T) to allow functions to modify variables without making copies.

Pointer Arithmetic:
Rust does not allow pointer arithmetic in safe code. This prevents mistakes like buffer overflows and out-of-bounds access.


Memory Management:
Rust uses a borrow checker and ownership system to prevent memory leaks. When a variable goes out of scope, Rust automatically deallocates memory (destruction) without needing explicit free() or delete() commands.


in summary Pointers in Rust are used to reference data in memory efficiently without copying.
Rust’s ownership and borrowing system ensures memory safety, and dynamic memory allocation is done using Box, Rc, Arc, and other structures.
Rust doesn’t allow pointer arithmetic in safe code to prevent common errors (e.g., buffer overflows), but you can use unsafe blocks if necessary, although they should be used with caution.



difference between &str and string

&str: This is a string slice, which is an immutable reference to a portion of a string. It does not own the data it references; instead, it borrows the data from another source, such as a String or a string literal. &str is lightweight and useful when you only need to view a part of a string without owning it. It is commonly used for function parameters when you do not need to modify the string.

String: This is a growable, heap-allocated, UTF-8 encoded string. It owns its data and can be modified and resized at runtime. You can create a new String by calling String::new() or by converting from a string slice using to_string(). String is mutable and can be used in scenarios where you need to build or modify strings dyn








A CPU, or Central Processing Unit, is the primary component in a computer that executes instructions and processes data from computer programs. It acts as the “brain” of the computer, handling tasks such as arithmetic, logic, and input/output operations. The CPU coordinates other components in the system and is essential for the computer’s overall functionality.

RAM (Random Access Memory)

Temporary, fast memory that stores:

Currently running programs,Active data being processed,Operating system components


Characteristics:

Volatile (loses data when power is off)
Much faster than storage drives
Directly accessible by CPU
Measured in GB (8GB, 16GB, etc.)



ROM (Read-Only Memory)

Permanent memory that contains:

BIOS/UEFI (Basic Input/Output System)
Firmware
Boot instructions


Characteristics:

Non-volatile (keeps data when power is off)
Can't be easily modified
Slower than RAM
Usually small capacity



How They Work Together:

ROM stores startup instructions
When computer starts, CPU reads ROM instructions
Operating system loads into RAM
CPU processes instructions, using RAM as working memory
Data flows between components via system bus


A stack is a part of memory that has a specific data structure.

When there is a new piece of data that should be stored, the stack will always put it “on top”. (push to the stack)
When a piece of data should be removed from the stack, it is also taken “from the top”. (pop off the stack)
using the last in, first out (LIFO) data structure.
All entries that are pushed to the stack are required to have a known, fixed size. The size should be known at compile time, and can not change during runtime. We can not put things of variable size in the stack (like a string that might grow in size).


heap

Heap memory in Rust is a part of the memory system used for dynamic memory allocation. Unlike stack memory, which is managed automatically by the compiler and has a fixed layout, heap memory is managed manually and is not bound to function scopes. This means that variables allocated on the heap can live longer than the function that created them, allowing for more flexible memory managem


A pointer is a general concept for a variable that contains an address in memory. This address refers to, or “points at,” some other data.


anything not implemented by a vetor dont have capacity




53 changes: 53 additions & 0 deletions src/calculator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
struct Calculator {
value: f64,
}

impl Calculator {
fn new() -> Calculator {
Calculator {
value: 5.0
}
}

fn add(&mut self, number: f64) -> f64 {
self.value += number;
self.value
}

fn subtract(&mut self, number: f64) -> f64 {
self.value -= number;
self.value
}

fn multiply(&mut self, number: f64) -> f64 {
self.value *= number;
self.value
}


fn divide(&mut self, number: f64) -> Result<f64, String> {
if number == 0.0 {
return Err(String::from("Cannot divide by zero!"));
}
self.value /= number;
Ok(self.value)
}

}



pub fn cal() {
let mut calc = Calculator::new();

println!("Adding 5: {}", calc.add(10.0));
println!("Multiplying by 2: {}", calc.multiply(2.0));
println!("Subtracting 3: {}", calc.subtract(3.0));


match calc.divide(2.0) {
Ok(result) => println!("Dividing by 2: {}", result),
Err(error) => println!("Error: {}", error),
}
}

22 changes: 22 additions & 0 deletions src/char.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

pub fn name(x: char, y: char) -> String {
let mut name = String::new();
name.push(x);
name.push(y);
name
}

pub fn myname(x: &str, y: &str) -> String {
let mut myname = String::new();
myname.push_str(x);
myname.push_str(y);
myname
}

pub fn intro_to_char() {
let name_result: String = name('D', 'o');
println!("The char result is: {}", name_result);

let myname_result: String = myname("Darey", "Olowo");
println!("my name are : {}", myname_result);
}
18 changes: 18 additions & 0 deletions src/f64operation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Floating-point Types

pub fn add(x: f64, y: f64) -> f64 {
x + y
}

pub fn minus(x: f64, y: f64) -> f64 {
x - y
}

pub fn rise(x: f64, y: f64) -> f64 {
x * y
}

pub fn split(x: f64, y: f64) -> f64 {
x / y
}

121 changes: 111 additions & 10 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,125 @@
mod u8operation;
mod f64operation;
mod char;
mod signed_integers;
mod calculator;

fn main() {
intro_to_u();
// intro_to_u();
// intro_to_f();
// crate::char::intro_to_char();
// convert_high();
// convert_high_to_low();
// crate::signed_integers::perform_operations();
crate::calculator::cal();

}


// function to encapsulate all integers




















// function to encapsulate all integers and to check for even numbers
fn intro_to_u() {
let sum_result: u8 = sum(5, 10);
println!("the sum result is: {}", sum_result);
let sum_result: u8 = u8operation::sum(5, 20);
println!("the sum result is: {}", sum_result);
println!(
"Is the sum result even? {}",
if crate::u8operation::is_even(sum_result) { "Yes" } else { "No" }
);

let subtract_result: u8 = u8operation::subtract(20, 15);
println!("the subtract result is: {}", subtract_result);
println!(
"Is the subtract result even? {}",
if crate::u8operation::is_even(subtract_result) {
"Yes"
} else {
"No"
}
);

let multiply_result: u8 = u8operation:: multiply(5, 12);
println!("the multiply result is {}", multiply_result);
println!(
"Is the multiply result even? {}",
if crate::u8operation::is_even(multiply_result) {
"Yes"
} else {
"No"
}
);

let divide_result: u8 = u8operation::divide(20, 4);
println!("the divide result is {}", divide_result);
println!(
"Is the divide result odd? {}",
if crate::u8operation::is_odd(divide_result) { "Yes" } else { "No" }
);
}

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





// functions for Floating points

fn intro_to_f() {
let add_result: f64 = f64operation::add(10.3.into(), 10.1.into());
println!("the add result is: {}", add_result);

let minus_result: f64 = f64operation::minus(25.5.into(), 5.5.into());
println!("the subract2 result is: {}", minus_result);

let rise_result: f64 = f64operation::rise(5.2.into(), 3.7.into());
println!("the multiply2 result is {}", rise_result);

let split_result: f64 = f64operation::split(30.9.into(), 2.3.into());
println!("the divide result is {}", split_result);
}


// subtract
// multiplication
// division





// how to convert u8 to u32

fn convert_high() {
let low: u8 = 255;
let high: u32 = low as u32;
println!("u8 value: {}, u32 value:{}", low, high);
}
//Function to convert high bit integer to low bit integer u32 to u8

fn convert_high_to_low() {
let high: u32 = 300;
let low: u8 = high as u8;
println!("u32 value: {}, u8 value: {}", high, low);
}







Loading