Skip to content

Commit c790d79

Browse files
authored
Add Karatsuba Algorithm (TheAlgorithms#317)
1 parent df16428 commit c790d79

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ These are for demonstration purposes only.
6262
- [x] [Armstrong Number](./src/math/armstrong_number.rs)
6363
- [x] [Permuted Congruential Random Number Generator](./src/math/random.rs)
6464
- [x] [Zeller's Congruence Algorithm](./src/math/zellers_congruence_algorithm.rs)
65+
- [x] [Karatsuba Multiplication Algorithm](./src/math/karatsuba_multiplication.rs)
6566

6667
## [Dynamic Programming](./src/dynamic_programming)
6768

src/math/karatsuba_multiplication.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
Finds the product of two numbers using Karatsuba Algorithm
3+
*/
4+
use std::cmp::max;
5+
const TEN: i128 = 10;
6+
7+
pub fn multiply(num1: i128, num2: i128) -> i128 {
8+
_multiply(num1, num2)
9+
}
10+
11+
fn _multiply(num1: i128, num2: i128) -> i128 {
12+
if num1 < 10 || num2 < 10 {
13+
return num1 * num2;
14+
}
15+
let mut num1_str = num1.to_string();
16+
let mut num2_str = num2.to_string();
17+
18+
let n = max(num1_str.len(), num2_str.len());
19+
num1_str = normalize(num1_str, n);
20+
num2_str = normalize(num2_str, n);
21+
22+
let a = &num1_str[0..n / 2];
23+
let b = &num1_str[n / 2..];
24+
let c = &num2_str[0..n / 2];
25+
let d = &num2_str[n / 2..];
26+
27+
let ac = _multiply(a.parse().unwrap(), c.parse().unwrap());
28+
let bd = _multiply(b.parse().unwrap(), d.parse().unwrap());
29+
let a_b: i128 = a.parse::<i128>().unwrap() + b.parse::<i128>().unwrap();
30+
let c_d: i128 = c.parse::<i128>().unwrap() + d.parse::<i128>().unwrap();
31+
let ad_bc = _multiply(a_b, c_d) - (ac + bd);
32+
33+
let m = n / 2 + n % 2;
34+
(TEN.pow(2 * m as u32) * ac) + (TEN.pow(m as u32) * ad_bc) + (bd)
35+
}
36+
37+
fn normalize(mut a: String, n: usize) -> String {
38+
for (counter, _) in (a.len()..n).enumerate() {
39+
a.insert(counter, '0');
40+
}
41+
a
42+
}
43+
#[cfg(test)]
44+
mod test {
45+
use super::*;
46+
47+
#[test]
48+
fn test_1() {
49+
let n1: i128 = 314159265;
50+
let n2: i128 = 314159265;
51+
let ans = multiply(n1, n2);
52+
assert_eq!(ans, n1 * n2);
53+
}
54+
55+
#[test]
56+
fn test_2() {
57+
let n1: i128 = 3141592653589793232;
58+
let n2: i128 = 2718281828459045233;
59+
let ans = multiply(n1, n2);
60+
assert_eq!(ans, n1 * n2);
61+
}
62+
63+
#[test]
64+
fn test_3() {
65+
let n1: i128 = 123456789;
66+
let n2: i128 = 101112131415;
67+
let ans = multiply(n1, n2);
68+
assert_eq!(ans, n1 * n2);
69+
}
70+
}

src/math/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod fast_fourier_transform;
55
mod fast_power;
66
mod gcd_of_n_numbers;
77
mod greatest_common_divisor;
8+
mod karatsuba_multiplication;
89
mod lcm_of_n_numbers;
910
mod linear_sieve;
1011
mod miller_rabin;
@@ -33,6 +34,7 @@ pub use self::gcd_of_n_numbers::gcd;
3334
pub use self::greatest_common_divisor::{
3435
greatest_common_divisor_iterative, greatest_common_divisor_recursive,
3536
};
37+
pub use self::karatsuba_multiplication::multiply;
3638
pub use self::lcm_of_n_numbers::lcm;
3739
pub use self::linear_sieve::LinearSieve;
3840
pub use self::miller_rabin::miller_rabin;

0 commit comments

Comments
 (0)