diff options
| author | Andrew Guschin <guschin.drew@gmail.com> | 2023-03-17 21:48:21 +0400 |
|---|---|---|
| committer | Andrew Guschin <guschin.drew@gmail.com> | 2023-03-17 21:48:21 +0400 |
| commit | bd08c736df80561de683bde825a4f4feca003898 (patch) | |
| tree | ac12e4dbfc1f24e52107110151bb153c96b7586c | |
| parent | 3afa13a155c3bc9101f39e4e4f209b65e5ebc88e (diff) | |
Добавлен конструктор Number::from_digits и изменён тип поля radix на u8
| -rw-r--r-- | sem2/rustfmt.toml | 1 | ||||
| -rw-r--r-- | sem2/src/main.rs | 8 | ||||
| -rw-r--r-- | sem2/src/mpn.rs | 117 |
3 files changed, 57 insertions, 69 deletions
diff --git a/sem2/rustfmt.toml b/sem2/rustfmt.toml new file mode 100644 index 0000000..df99c69 --- /dev/null +++ b/sem2/rustfmt.toml @@ -0,0 +1 @@ +max_width = 80 diff --git a/sem2/src/main.rs b/sem2/src/main.rs index b190a96..a983772 100644 --- a/sem2/src/main.rs +++ b/sem2/src/main.rs @@ -12,7 +12,9 @@ fn main() { let radix = match radix.parse::<i32>() { Ok(number) => { if number > 36 || number < 2 { - println!("Система счисления должна принадлежать отрезку [2,36]"); + println!( + "Система счисления должна принадлежать отрезку [2,36]" + ); return; } number @@ -32,14 +34,14 @@ fn main() { Err(_) => return, }; - let a = match mpn::Number::parse(&a_text, radix as usize) { + let a = match mpn::Number::parse(&a_text, radix as u8) { Ok(number) => number, Err(what) => { println!("{what}"); return; } }; - let b = match mpn::Number::parse(&b_text, radix as usize) { + let b = match mpn::Number::parse(&b_text, radix as u8) { Ok(number) => number, Err(what) => { println!("{what}"); diff --git a/sem2/src/mpn.rs b/sem2/src/mpn.rs index 1cd0383..b8314e7 100644 --- a/sem2/src/mpn.rs +++ b/sem2/src/mpn.rs @@ -3,7 +3,7 @@ use std::fmt; use std::ops::{Add, Div, Mul, Rem, Sub}; pub struct Number { - radix: usize, + radix: u8, digits: Vec<u8>, } @@ -17,13 +17,13 @@ impl Clone for Number { } impl Number { - pub fn parse(snum: &str, radix: usize) -> Result<Number, &str> { + pub fn parse(snum: &str, radix: u8) -> Result<Number, &str> { let snum = snum.as_bytes(); let mut digits = Vec::new(); for i in (0..snum.len()).rev() { match Number::parse_digit(snum[i]) { Some(digit) => { - if digit as usize >= radix { + if digit >= radix { return Err("Аргумент не является числом"); } else { digits.push(digit); @@ -34,7 +34,23 @@ impl Number { } } } - return Ok(Number { radix, digits }); + return Ok(Number { radix, digits }.fix_leading_zeros()); + } + + pub fn from_digits(digits: &Vec<u8>, radix: u8) -> Result<Number, String> { + for digit in digits { + if *digit >= radix { + return Err( + "Переданные цифры не соответствуют системе счисления" + .to_string(), + ); + } + } + return Ok(Number { + radix, + digits: digits.clone(), + } + .fix_leading_zeros()); } pub fn len(&self) -> usize { @@ -110,7 +126,8 @@ impl Add for Number { digit += other.digits[i] as usize; } digit += k; - let (div, rem) = (digit / self.radix, digit % self.radix); + let (div, rem) = + (digit / self.radix as usize, digit % self.radix as usize); digit = rem; k = div; digits.push(digit as u8); @@ -119,10 +136,7 @@ impl Add for Number { digits.push(k as u8); } - return Number { - radix: self.radix, - digits, - }; + return Number::from_digits(&digits, self.radix).unwrap(); } } @@ -154,11 +168,7 @@ impl Sub for Number { digits.push(k as u8); } - return Number { - radix: self.radix, - digits, - } - .fix_leading_zeros(); + return Number::from_digits(&digits, self.radix).unwrap(); } } @@ -179,17 +189,14 @@ impl Mul for Number { for i in 0..n { let ui = self.digits[i] as usize; let t = ui * vj + digits[i + j] as usize + k; - digits[i + j] = (t % self.radix) as u8; - k = t / self.radix; + digits[i + j] = (t % self.radix as usize) as u8; + k = t / self.radix as usize; } digits[n + j] = k as u8; } } - return Number { - radix: self.radix, - digits, - } - .fix_leading_zeros(); + + return Number::from_digits(&digits, self.radix).unwrap(); } } @@ -201,10 +208,7 @@ impl Number { if self < other { return Ok(( - Number { - radix: self.radix, - digits: vec![0], - }, + Number::from_digits(&vec![0], self.radix).unwrap(), self, )); } @@ -213,37 +217,30 @@ impl Number { 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; + let d = rem * radix as usize + a[j] as usize; + q.push((d / b as usize) as u8); + rem = d % b as usize; } q.reverse(); - return (q, rem); + return (q, rem as u8); } if other.len() == 1 { - let (div, rem) = div_digit(&self.digits, other.digits[0], self.radix as u8); + let (div, rem) = + div_digit(&self.digits, other.digits[0], self.radix as u8); return Ok(( - Number { - radix: self.radix, - digits: div, - } - .fix_leading_zeros(), - Number { - radix: self.radix, - digits: vec![rem], - } - .fix_leading_zeros(), + Number::from_digits(&div, self.radix).unwrap(), + Number::from_digits(&vec![rem], self.radix).unwrap(), )); } fn mul_digit(a: &Vec<u8>, b: u8, radix: u8) -> Vec<u8> { let mut c = vec![0; a.len() + 1]; - let mut carry = 0 as i32; + let mut carry = 0; for i in 0..a.len() { - 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; + let dig = a[i] as usize * b as usize + carry; + c[i] = (dig % radix as usize) as u8; + carry = dig / radix as usize; } *c.last_mut().unwrap() = carry as u8; return c; @@ -254,7 +251,7 @@ impl Number { let b = self.radix as i32; let v1 = other.digits[other.len() - 1]; - let d = self.radix as u8 / (v1 + 1); + let d = self.radix / (v1 + 1); let mut u = mul_digit(&self.digits, d, self.radix as u8); let mut v = mul_digit(&other.digits, d, self.radix as u8); @@ -277,16 +274,13 @@ impl Number { qc }; let u_sub = &u[u.len() - 1 - (j + n)..=u.len() - 1 - j]; - let u_sub = Number { - radix: self.radix, - digits: Vec::from(u_sub), - } - .fix_leading_zeros(); - let qv = Number { - radix: other.radix, - digits: mul_digit(&v, q as u8, other.radix as u8), - } - .fix_leading_zeros(); + let u_sub = + Number::from_digits(&Vec::from(u_sub), self.radix).unwrap(); + let qv = Number::from_digits( + &mul_digit(&v, q as u8, other.radix), + other.radix, + ) + .unwrap(); if u_sub >= qv { let p = u_sub - qv; for i in 0..n + 1 { @@ -300,18 +294,9 @@ impl Number { } quo.reverse(); - 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(); + let div = Number::from_digits(&quo, self.radix).unwrap(); + let rem = Number::from_digits(&rem_digits, self.radix).unwrap(); return Ok((div, rem)); } |