Skip to content

Commit c2009cd

Browse files
mengfansheng-gitchangweidalaifu6vil02
authored
feat: add multiply.rs (#716)
* add multiply.rs * Optimized code * Remove redundant references * modify test * modify test name * modify code * Determine the legitimacy of a string * Modify judgment conditions * Optimization code * modify code --------- Co-authored-by: mengfansheng <[email protected]> Co-authored-by: Piotr Idzik <[email protected]>
1 parent bba0b0d commit c2009cd

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* [Sudoku](https://github.com/TheAlgorithms/Rust/blob/master/src/backtracking/sudoku.rs)
1111
* Big Integer
1212
* [Fast Factorial](https://github.com/TheAlgorithms/Rust/blob/master/src/big_integer/fast_factorial.rs)
13+
* [Multiply](https://github.com/TheAlgorithms/Rust/blob/master/src/big_integer/multiply.rs)
1314
* [Poly1305](https://github.com/TheAlgorithms/Rust/blob/master/src/big_integer/poly1305.rs)
1415
* Bit Manipulation
1516
* [Counting Bits](https://github.com/TheAlgorithms/Rust/blob/master/src/bit_manipulation/counting_bits.rs)

src/big_integer/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#![cfg(feature = "big-math")]
22

33
mod fast_factorial;
4+
mod multiply;
45
mod poly1305;
56

67
pub use self::fast_factorial::fast_factorial;
8+
pub use self::multiply::multiply;
79
pub use self::poly1305::Poly1305;

src/big_integer/multiply.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/// Performs long multiplication on string representations of non-negative numbers.
2+
pub fn multiply(num1: &str, num2: &str) -> String {
3+
if !is_valid_nonnegative(num1) || !is_valid_nonnegative(num2) {
4+
panic!("String does not conform to specification")
5+
}
6+
7+
if num1 == "0" || num2 == "0" {
8+
return "0".to_string();
9+
}
10+
let output_size = num1.len() + num2.len();
11+
12+
let mut mult = vec![0; output_size];
13+
for (i, c1) in num1.chars().rev().enumerate() {
14+
for (j, c2) in num2.chars().rev().enumerate() {
15+
let mul = c1.to_digit(10).unwrap() * c2.to_digit(10).unwrap();
16+
// It could be a two-digit number here.
17+
mult[i + j + 1] += (mult[i + j] + mul) / 10;
18+
// Handling rounding. Here's a single digit.
19+
mult[i + j] = (mult[i + j] + mul) % 10;
20+
}
21+
}
22+
if mult[output_size - 1] == 0 {
23+
mult.pop();
24+
}
25+
mult.iter().rev().map(|&n| n.to_string()).collect()
26+
}
27+
28+
pub fn is_valid_nonnegative(num: &str) -> bool {
29+
num.chars().all(char::is_numeric) && !num.is_empty() && (!num.starts_with('0') || num == "0")
30+
}
31+
32+
#[cfg(test)]
33+
mod tests {
34+
use super::*;
35+
macro_rules! test_multiply {
36+
($($name:ident: $inputs:expr,)*) => {
37+
$(
38+
#[test]
39+
fn $name() {
40+
let (s, t, expected) = $inputs;
41+
assert_eq!(multiply(s, t), expected);
42+
assert_eq!(multiply(t, s), expected);
43+
}
44+
)*
45+
}
46+
}
47+
48+
test_multiply! {
49+
multiply0: ("2", "3", "6"),
50+
multiply1: ("123", "456", "56088"),
51+
multiply_zero: ("0", "222", "0"),
52+
other_1: ("99", "99", "9801"),
53+
other_2: ("999", "99", "98901"),
54+
other_3: ("9999", "99", "989901"),
55+
other_4: ("192939", "9499596", "1832842552644"),
56+
}
57+
58+
macro_rules! test_multiply_with_wrong_input {
59+
($($name:ident: $inputs:expr,)*) => {
60+
$(
61+
#[test]
62+
#[should_panic]
63+
fn $name() {
64+
let (s, t) = $inputs;
65+
multiply(s, t);
66+
}
67+
)*
68+
}
69+
}
70+
test_multiply_with_wrong_input! {
71+
empty_input: ("", "121"),
72+
leading_zero: ("01", "3"),
73+
wrong_characters: ("2", "12d4"),
74+
wrong_input_and_zero_1: ("0", "x"),
75+
wrong_input_and_zero_2: ("y", "0"),
76+
}
77+
}

0 commit comments

Comments
 (0)