diff options
| author | Andrew Guschin <guschin.drew@gmail.com> | 2023-03-17 20:46:24 +0400 |
|---|---|---|
| committer | Andrew Guschin <guschin.drew@gmail.com> | 2023-03-17 20:49:24 +0400 |
| commit | 0a3330a6959405913fdd14516e72a587ce6eefc6 (patch) | |
| tree | c67f6b6cdc8690b4ee1eba607524828a64ecf318 | |
| parent | a4d1ce7bca0c2110638275d9e4fd52e723ac0c9c (diff) | |
Добавлена операция деления, исправлена ошибка при сравнении чисел.
| -rw-r--r-- | sem2/src/main.rs | 19 | ||||
| -rw-r--r-- | sem2/src/mpn.rs | 119 |
2 files changed, 100 insertions, 38 deletions
diff --git a/sem2/src/main.rs b/sem2/src/main.rs index 2fea2b1..d2c7376 100644 --- a/sem2/src/main.rs +++ b/sem2/src/main.rs @@ -62,22 +62,23 @@ fn main() { } }; - let mpn_mul_start = Instant::now(); - let mpn_mul = a / b; - let mpn_mul_elapsed = mpn_mul_start.elapsed(); + let mpn_start = Instant::now(); + let mpn_res = a.div_rem(b); + let mpn_elapsed = mpn_start.elapsed(); - let rug_mul_start = Instant::now(); - let _rug_mul = a_rug * b_rug; - let rug_mul_elapsed = rug_mul_start.elapsed(); + let rug_start = Instant::now(); + let _rug_res = a_rug.div_rem(b_rug); + let rug_elapsed = rug_start.elapsed(); - println!("Произведение: {}", mpn_mul); + println!("Частное: {}", mpn_res.0); + println!("Остаток: {}", mpn_res.1); println!( "Операция произведения выполнена в mpn за {} наносекунд", - mpn_mul_elapsed.as_nanos() + mpn_elapsed.as_nanos() ); println!( "Операция произведения выполнена в rug за {} наносекунд", - rug_mul_elapsed.as_nanos() + rug_elapsed.as_nanos() ); } diff --git a/sem2/src/mpn.rs b/sem2/src/mpn.rs index cd8ecdf..caccc33 100644 --- a/sem2/src/mpn.rs +++ b/sem2/src/mpn.rs @@ -1,6 +1,6 @@ use std::cmp::{max, Ordering}; use std::fmt; -use std::ops::{Add, Div, Mul, Sub}; +use std::ops::{Add, Div, Mul, Rem, Sub}; pub struct Number { radix: usize, @@ -184,25 +184,61 @@ impl Mul for Number { } } -impl Div for Number { - type Output = Self; +impl Number { + pub fn div_rem(self, other: Self) -> (Self, Self) { + if self < other { + return ( + Number { + radix: self.radix, + digits: vec![0], + }, + self, + ); + } + + fn div_digit(a: &Vec<u8>, b: u8, radix: u8) -> (Vec<u8>, u8) { + let mut q = Vec::new(); + let mut rem = 0; + for j in (0..a.len()).rev() { + let d = rem as i32 * radix as i32 + a[j] as i32; + q.push((d / b as i32) as u8); + rem = (d % b as i32) as u8; + } + q.reverse(); + return (q, rem); + } + + if other.len() == 1 { + let (div, rem) = div_digit(&self.digits, other.digits[0], self.radix as u8); + return ( + Number { + radix: self.radix, + digits: div, + } + .fix_leading_zeros(), + Number { + radix: self.radix, + digits: vec![rem], + } + .fix_leading_zeros(), + ); + } - fn div(self, other: Self) -> Self::Output { fn mul_digit(a: &Vec<u8>, b: u8, radix: u8) -> Vec<u8> { let mut c = vec![0; a.len() + 1]; - let mut carry = 0; + let mut carry = 0 as i32; for i in 0..a.len() { - let dig = a[i] * b; - c[i] = dig % radix + carry; - carry = dig / radix; + let dig = (a[i] as i32 * b as i32) as i32 + carry; + c[i] = (dig % radix as i32) as u8; + carry = dig / radix as i32; } - *c.last_mut().unwrap() = carry; + *c.last_mut().unwrap() = carry as u8; return c; } let n = other.len(); let m = self.len() - n; - let b = self.radix as u8; + let b = self.radix as i32; let v1 = other.digits[other.len() - 1]; let d = self.radix as u8 / (v1 + 1); @@ -211,28 +247,22 @@ impl Div for Number { let mut v = mul_digit(&other.digits, d, self.radix as u8); v.pop(); - // println!("{d} {u:?} {v:?}"); - let mut quo = Vec::new(); for j in 0..=m { - // println!("{:?}", u); - let uj = u[u.len() - 1 - j]; - let v1 = v[v.len() - 1]; + let uj = u[u.len() - 1 - j] as i32; + let v1 = v[v.len() - 1] as i32; let q = if uj == v1 { b - 1 } else { - let uj1 = u[u.len() - 1 - (j + 1)]; - let uj2 = u[u.len() - 1 - (j + 2)]; - let v2 = v[v.len() - 2]; + let uj1 = u[u.len() - 1 - (j + 1)] as i32; + let uj2 = u[u.len() - 1 - (j + 2)] as i32; + let v2 = v[v.len() - 2] as i32; let mut qc = (uj * b + uj1) / v1; while v2 * qc > (uj * b + uj1 - qc * v1) * b + uj2 { qc -= 1; } qc }; - // println!("{uj} {v1}"); - // println!("{q}"); - quo.push(q); let u_sub = &u[u.len() - 1 - (j + n)..=u.len() - 1 - j]; let u_sub = Number { radix: self.radix, @@ -241,23 +271,54 @@ impl Div for Number { .fix_leading_zeros(); let qv = Number { radix: other.radix, - digits: mul_digit(&v, q, other.radix as u8), + digits: mul_digit(&v, q as u8, other.radix as u8), } .fix_leading_zeros(); - let p = u_sub - qv; - for i in 0..n + 1 { - let idx = u.len() - 1 - (j + n - i); - u[idx] = if i < p.len() { p.digits[i] } else { 0 }; + if u_sub >= qv { + let p = u_sub - qv; + for i in 0..n + 1 { + let idx = u.len() - 1 - (j + n - i); + u[idx] = if i < p.len() { p.digits[i] } else { 0 }; + } + quo.push(q as u8); + } else { + quo.push((q - 1) as u8); } } - // println!("{:?}", quo); quo.reverse(); - return Number { + let div = Number { radix: self.radix, digits: quo, } .fix_leading_zeros(); + + let (rem_digits, _) = div_digit(&u, d, self.radix as u8); + let rem = Number { + radix: self.radix, + digits: rem_digits, + } + .fix_leading_zeros(); + + return (div, rem); + } +} + +impl Div for Number { + type Output = Self; + + fn div(self, other: Self) -> Self::Output { + let (div, _) = self.div_rem(other); + return div; + } +} + +impl Rem for Number { + type Output = Self; + + fn rem(self, other: Self) -> Self::Output { + let (_, rem) = self.div_rem(other); + return rem; } } @@ -299,7 +360,7 @@ impl Ord for Number { return Ordering::Greater; } - for i in 0..self.len() { + for i in (0..self.len()).rev() { let l = self.digits[i]; let r = other.digits[i]; if l != r { |