First pass
This commit is contained in:
commit
2aa53c41dc
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "realNumbers"
|
||||
version = "0.1.0"
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "realNumbers"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
167
src/lib.rs
Normal file
167
src/lib.rs
Normal file
@ -0,0 +1,167 @@
|
||||
use std::collections::HashMap;
|
||||
use std::ops::{Add, Sub};
|
||||
use std::cmp::max;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Real {
|
||||
int_part: i32,
|
||||
decimal_parts: HashMap<i32, i8>
|
||||
}
|
||||
|
||||
impl Real {
|
||||
pub fn new_int(int_part: i32) -> Real {
|
||||
Real { int_part: int_part, decimal_parts: HashMap::new() }
|
||||
}
|
||||
|
||||
pub fn new(int_part: i32, decimal_parts: HashMap<i32, i8>) -> Real {
|
||||
Real { int_part: int_part, decimal_parts: decimal_parts }
|
||||
}
|
||||
|
||||
pub fn from_string(s: &str) -> Real {
|
||||
let first_period_index = s.find('.');
|
||||
dbg!(first_period_index);
|
||||
match first_period_index {
|
||||
None => {
|
||||
Real { int_part: s.parse::<i32>().unwrap(), decimal_parts: HashMap::new() }
|
||||
},
|
||||
Some(idx) => {
|
||||
let int_part = s[0..idx].parse::<i32>().unwrap();
|
||||
dbg!(int_part);
|
||||
let decimal_string = &s[idx+1..];
|
||||
dbg!(decimal_string);
|
||||
|
||||
match decimal_string.find('.') {
|
||||
Some(_) => {
|
||||
panic!("Found two periods in input string");
|
||||
},
|
||||
None => {
|
||||
let length = decimal_string.len();
|
||||
dbg!(length);
|
||||
let mut decimal_parts = HashMap::new();
|
||||
for idx in 0..length {
|
||||
let c = decimal_string.as_bytes()[idx] as char;
|
||||
let num = c.to_digit(10).unwrap();
|
||||
if num != 0 {
|
||||
decimal_parts.entry(idx as i32).or_insert(num as i8);
|
||||
}
|
||||
}
|
||||
Real { int_part: int_part, decimal_parts: decimal_parts }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Real {
|
||||
type Output = Real;
|
||||
|
||||
fn add(self, other: Real) -> Real {
|
||||
let mut int_part = self.int_part + other.int_part;
|
||||
let mut decimal_part = HashMap::new();
|
||||
let highest_index = max(
|
||||
self.decimal_parts.keys().max().unwrap_or(&0),
|
||||
other.decimal_parts.keys().max().unwrap_or(&0));
|
||||
let mut carry = false;
|
||||
for idx in (0..=*highest_index).rev() {
|
||||
let borrowed = &idx;
|
||||
let sum = self.decimal_parts.get(borrowed).unwrap_or(&0) + other.decimal_parts.get(borrowed).unwrap_or(&0) + if carry {1} else {0};
|
||||
carry = sum > 9;
|
||||
let units = sum % 10;
|
||||
if units != 0 {
|
||||
decimal_part.entry( *borrowed).or_insert(units);
|
||||
}
|
||||
}
|
||||
if carry {
|
||||
int_part += 1;
|
||||
}
|
||||
Real::new(int_part, decimal_part)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Real {
|
||||
type Output = Real;
|
||||
|
||||
fn sub(self, other: Real) -> Real {
|
||||
let int_part = self.int_part - other.int_part;
|
||||
Real::new_int(int_part)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Real {
|
||||
fn eq(&self, other: &Real) -> bool {
|
||||
// And also compare decimals
|
||||
self.int_part == other.int_part &&
|
||||
self.decimal_parts == other.decimal_parts
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::Real;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = 2 + 2;
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn int_addition() {
|
||||
let one = Real::new_int(1);
|
||||
let two = Real::new_int(2);
|
||||
assert_eq!(one + two, Real::new_int(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn real_addition() {
|
||||
// Basic equality
|
||||
assert_eq!(
|
||||
Real::from_string("1.23") + Real::from_string("3.45"),
|
||||
Real::from_string("4.68")
|
||||
);
|
||||
|
||||
// Basic inequality
|
||||
assert_ne!(
|
||||
Real::from_string("1.23") + Real::from_string("3.45"),
|
||||
Real::from_string("4.70")
|
||||
);
|
||||
|
||||
// Carry
|
||||
assert_eq!(
|
||||
Real::from_string("0.09") + Real::from_string("0.01"),
|
||||
Real::from_string("0.1")
|
||||
);
|
||||
|
||||
// Multiple carry
|
||||
assert_eq!(
|
||||
Real::from_string("0.99") + Real::from_string("0.01"),
|
||||
Real::from_string("1")
|
||||
);
|
||||
|
||||
// Ignore trailing zeros
|
||||
assert_eq!(
|
||||
Real::from_string("1.00"),
|
||||
Real::from_string("1")
|
||||
);
|
||||
assert_eq!(
|
||||
Real::from_string("2.00000"),
|
||||
Real::from_string("2.00")
|
||||
);
|
||||
assert_eq!(
|
||||
Real::from_string("3.000"),
|
||||
Real::new_int(3)
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn subtraction() {
|
||||
let three = Real::new_int(3);
|
||||
let one = Real::new_int(1);
|
||||
assert_eq!(three - one, Real::new_int(2));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user