summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Guschin <guschin.drew@gmail.com>2023-03-17 21:48:21 +0400
committerAndrew Guschin <guschin.drew@gmail.com>2023-03-17 21:48:21 +0400
commitbd08c736df80561de683bde825a4f4feca003898 (patch)
treeac12e4dbfc1f24e52107110151bb153c96b7586c
parent3afa13a155c3bc9101f39e4e4f209b65e5ebc88e (diff)
Добавлен конструктор Number::from_digits и изменён тип поля radix на u8
-rw-r--r--sem2/rustfmt.toml1
-rw-r--r--sem2/src/main.rs8
-rw-r--r--sem2/src/mpn.rs117
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));
}