feat(*): Approximations + fix print

This commit is contained in:
gbrochar 2023-11-23 07:26:38 +01:00
parent 0628e54d6e
commit 36362458c8
4 changed files with 78 additions and 20 deletions

View File

@ -10,16 +10,16 @@ pub mod maths;
pub fn format(v: &Vec<GaussianRational>) -> String {
let mut format;
format = v[0].format();
format = v[0].format(false);
if v.len() > 1 {
if format == "" {
format = format!("{}x", v[1].format());
format = format!("{}x", v[1].format(true));
} else {
format = format!("{format} + {}x", v[1].format());
format = format!("{format} + {}x", v[1].format(true));
}
}
for i in 2..v.len() {
let tmp = v[i].format();
let tmp = v[i].format(true);
if tmp != "" {
if format == ""{
format = format!("{tmp}x^{i}");

View File

@ -20,6 +20,7 @@ fn main() {
println!("{} = 0", computorv1::format(&evaluated));
computorv1::maths::solver::solve(evaluated);
} else {
println!("{} is equal to:", args[1]);
println!("{}", computorv1::format(&evaluated));
}
}

View File

@ -16,6 +16,34 @@ fn one() -> GaussianRational {
GaussianRational::new(Rational::new(1, 1), Rational::new(0, 1))
}
fn approx_sqrt_f64(n: f64) -> f64 {
let n = n as f64;
let mut result = n + 1.;
let mut factor = 1.;
while factor > f64::EPSILON {
while result * result > n {
result /= 1. + factor;
}
result *= 1. + factor;
factor /= 2.;
}
result
}
fn approx_sqrt(n: i128) -> f64 {
let n = n as f64;
let mut result = n;
let mut factor = 1.;
while factor > f64::EPSILON {
while result * result > n {
result /= 1. + factor;
}
result *= 1. + factor;
factor /= 2.;
}
result
}
fn get_prime_factors(mut n: i128) -> Vec<i128> {
if n == 0 {
return [0].to_vec();
@ -106,6 +134,9 @@ impl Rational {
copy.denominator *= 5;
five_count += 1;
}
if copy.numerator < 0 {
copy.numerator *= -1;
}
format!("{}.{}", copy.numerator / copy.denominator, copy.numerator % copy.denominator)
}
@ -249,12 +280,13 @@ impl GaussianRational {
GaussianRational::new(self.real, -1 * self.imaginary)
}
pub fn format(&self) -> String {
match (self.real().is_zero(), self.imaginary.is_zero()) {
(true, true) => format!(""),
(true, false) => format!("{}i", self.imaginary.format()),
(false, true) => format!("{}", self.real.format()),
(false, false) => format!("{} + {}i", self.real.format(), self.imaginary.format())
pub fn format(&self, parenthesis: bool) -> String {
match (self.real().is_zero(), self.imaginary.is_zero(), parenthesis) {
(true, true, _) => format!(""),
(true, false, _) => format!("{}i", self.imaginary.format()),
(false, true, _) => format!("{}", self.real.format()),
(false, false, false) => format!("{} + {}i", self.real.format(), self.imaginary.format()),
(false, false, true) => format!("({} + {}i)", self.real.format(), self.imaginary.format())
}
}
@ -489,10 +521,10 @@ mod tests {
let b = GaussianRational::new(zero, rational);
let c = GaussianRational::new(whole, zero);
let d = GaussianRational::new(whole, rational);
assert_eq!(a.format(), String::from(""));
assert_eq!(b.format(), String::from("5/3i"));
assert_eq!(c.format(), String::from("5"));
assert_eq!(d.format(), String::from("5 + 5/3i"));
assert_eq!(a.format(false), String::from(""));
assert_eq!(b.format(false), String::from("5/3i"));
assert_eq!(c.format(false), String::from("5"));
assert_eq!(d.format(false), String::from("5 + 5/3i"));
}
#[test]

View File

@ -13,7 +13,7 @@ fn degree_one(equation: Vec<GaussianRational>) {
println!("Polynomial degree: 1");
let x = minus_one() * equation[0] / equation[1];
println!("The solution is");
let mut format = x.format();
let mut format = x.format(false);
if format == "" {
format = String::from("0");
}
@ -56,6 +56,7 @@ fn simplify_sqrt(n: i128) -> (i128, i128) {
(natural, irrational)
}
// Eric Naslund for the math https://math.stackexchange.com/questions/44406/how-do-i-get-the-square-root-of-a-complex-number
fn comp_sqrt(c: GaussianRational) -> MyCompSqrt {
let real = c.real();
let imag = c.imaginary();
@ -107,7 +108,7 @@ fn comp_sqrt(c: GaussianRational) -> MyCompSqrt {
}
}
fn get_strings(left_part: Rational, sqrt_delta: MySqrt) -> (String, String, String, String, String, String) {
fn get_strings(left_part: Rational, sqrt_delta: &MySqrt) -> (String, String, String, String, String, String) {
let mut a = left_part.numerator;
let mut b = sqrt_delta.numerator_natural;
if b < 0 {
@ -191,12 +192,12 @@ fn degree_two_complex(a: GaussianRational, b: GaussianRational, c: GaussianRatio
let b = b / GaussianRational::new(Rational::new(-2, 1), Rational::new(0, 1));
let mut sign = '+';
let mut sign = '±';
if sqrt_delta.sign < 0 {
sign = '-';
sign = '';
}
let (s1, s2, s3, s4, s5, s6) = get_strings(sqrt_delta.rational, sqrt_delta.sqrt);
let (s1, s2, s3, s4, s5, s6) = get_strings(sqrt_delta.rational, &sqrt_delta.sqrt);
let mut string1 = String::from("");
let mut string2 = String::from("");
let mut string3 = String::from("");
@ -218,7 +219,7 @@ fn degree_two_complex(a: GaussianRational, b: GaussianRational, c: GaussianRatio
}
string1 = format!("{string1} /{s1}\\ ");
string2 = format!("{string2} + sqrt | {s2} | ");
string2 = format!("{string2} ± sqrt | {s2} | ");
string3 = format!("{string3} \\{s3}/ ");
if b.imaginary.numerator != 0 {
@ -241,9 +242,19 @@ fn degree_two_complex(a: GaussianRational, b: GaussianRational, c: GaussianRatio
string2 = format!("{string2}{sign} sqrt | {s5} | i");
string3 = format!("{string3} \\{s6}/ ");
println!("The two solutions are:");
println!("{string1}");
println!("{string2}");
println!("{string3}");
println!("Approximations:");
let sqrt = sqrt_delta.sqrt.numerator_natural as f64 * approx_sqrt(sqrt_delta.sqrt.numerator_irrational);
let left = b.real.numerator as f64 / b.real.denominator as f64;
let left_sqrt = approx_sqrt_f64((sqrt_delta.rational.numerator as f64 + sqrt) / sqrt_delta.rational.denominator as f64);
let right = b.imaginary.numerator as f64 / b.imaginary.denominator as f64;
let right_sqrt = sqrt_delta.sign as f64 * approx_sqrt_f64((-sqrt_delta.rational.numerator as f64 + sqrt) / sqrt_delta.rational.denominator as f64);
println!("{}", format!("{} + {}i", left + left_sqrt, right + right_sqrt).split("+ -").collect::<Vec<_>>().join("- "));
println!("{}", format!("{} + {}i", left - left_sqrt, right - right_sqrt).split("+ -").collect::<Vec<_>>().join("- "));
}
fn sqrt(n: Rational, a: Rational) -> MySqrt {
@ -320,6 +331,20 @@ fn print_degree_two_real(left_part: Rational, sqrt_delta: MySqrt, imaginary: boo
println!("{}{string}", " ".repeat(4 + (len - string.chars().count()) / 2));
println!("x = {}", "-".repeat(len));
println!("{}{d}", " ".repeat(4 + (len - d.to_string().len()) / 2));
let mut right = (sqrt_delta.numerator_natural as f64 * approx_sqrt(sqrt_delta.numerator_irrational)) / left_part.denominator as f64;
let left = left_part.numerator as f64 / left_part.denominator as f64;
if right < 0. {
right *= -1.;
}
println!("Approximations:");
if imaginary == true {
println!("{} - {}i", left, right);
println!("{} + {}i", left, right);
} else {
println!("{}", left - right);
println!("{}", left + right);
}
} else if string.len() > 0 {
println!("x = {string}");
} else {