Skip to content

Commit 20f74d4

Browse files
Swastyygithub-actionsPanquesito7ayaankhan98
authored
feat: Karatsuba algorithm (TheAlgorithms#1550)
* karatsuba algorithm * Update karatsuba_algorithm_for_fast_multiplication.cpp * Update karatsuba_algorithm_for_fast_multiplication.cpp * Update karatsuba_algorithm_for_fast_multiplication.cpp * Update karatsuba_algorithm_for_fast_multiplication.cpp * Update karatsuba_algorithm_for_fast_multiplication.cpp * Update karatsuba_algorithm_for_fast_multiplication.cpp * updating DIRECTORY.md * clang-format and clang-tidy fixes for 180f356 * Update divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp Co-authored-by: David Leal <[email protected]> * Update divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp Co-authored-by: David Leal <[email protected]> * Update divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp Co-authored-by: David Leal <[email protected]> * clang-format and clang-tidy fixes for 2b8d67a * Apply suggestions from code review Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal <[email protected]> Co-authored-by: Ayaan Khan <[email protected]>
1 parent faa58ed commit 20f74d4

File tree

2 files changed

+170
-0
lines changed

2 files changed

+170
-0
lines changed

DIRECTORY.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@
6666
* [Trie Tree](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/trie_tree.cpp)
6767
* [Trie Using Hashmap](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/data_structures/trie_using_hashmap.cpp)
6868

69+
## Divide And Conquer
70+
* [Karatsuba Algorithm For Fast Multiplication](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/divide_and_conquer/karatsuba_algorithm_for_fast_multiplication.cpp)
71+
6972
## Dynamic Programming
7073
* [0 1 Knapsack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/0_1_knapsack.cpp)
7174
* [Abbreviation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/dynamic_programming/abbreviation.cpp)
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
/**
2+
* @file
3+
* @brief Implementation of the [Karatsuba algorithm for fast
4+
* multiplication](https://en.wikipedia.org/wiki/Karatsuba_algorithm)
5+
* @details
6+
* Given two strings in binary notation we want to multiply them and return the
7+
* value Simple approach is to multiply bits one by one which will give the time
8+
* complexity of around O(n^2). To make it more efficient we will be using
9+
* Karatsuba' algorithm to find the product which will solve the problem
10+
* O(nlogn) of time.
11+
* @author [Swastika Gupta](https://github.com/Swastyy)
12+
*/
13+
14+
#include <cassert> /// for assert
15+
#include <cstring> /// for string
16+
#include <iostream> /// for IO operations
17+
#include <vector> /// for std::vector
18+
19+
/**
20+
* @namespace divide_and_conquer
21+
* @brief Divide and Conquer algorithms
22+
*/
23+
namespace divide_and_conquer {
24+
/**
25+
* @namespace karatsuba_algorithm
26+
* @brief Functions for the [Karatsuba algorithm for fast
27+
* multiplication](https://en.wikipedia.org/wiki/Karatsuba_algorithm)
28+
*/
29+
namespace karatsuba_algorithm {
30+
/**
31+
* @brief Helper function for the main function, that implements Karatsuba's
32+
* algorithm for fast multiplication
33+
* @param first the input string 1
34+
* @param second the input string 2
35+
* @returns the concatenated string
36+
*/
37+
std::string addStrings(std::string first, std::string second) {
38+
std::string result; // To store the resulting sum bits
39+
40+
int64_t len1 = first.size();
41+
int64_t len2 = second.size();
42+
int64_t length = std::max(len1, len2);
43+
std::string zero = "0";
44+
if (len1 < len2) // make the string lengths equal
45+
{
46+
for (int64_t i = 0; i < len2 - len1; i++) {
47+
zero += first;
48+
first = zero;
49+
}
50+
} else if (len1 > len2) {
51+
zero = "0";
52+
for (int64_t i = 0; i < len1 - len2; i++) {
53+
zero += second;
54+
second = zero;
55+
}
56+
}
57+
int64_t carry = 0;
58+
for (int64_t i = length - 1; i >= 0; i--) {
59+
int64_t firstBit = first.at(i) - '0';
60+
int64_t secondBit = second.at(i) - '0';
61+
62+
int64_t sum = (firstBit ^ secondBit ^ carry) + '0'; // sum of 3 bits
63+
std::string temp;
64+
temp = std::to_string(sum);
65+
temp += result;
66+
result = temp;
67+
68+
carry = (firstBit & secondBit) | (secondBit & carry) |
69+
(firstBit & carry); // sum of 3 bits
70+
}
71+
72+
if (carry) {
73+
result = '1' + result; // adding 1 incase of overflow
74+
}
75+
return result;
76+
}
77+
/**
78+
* @brief The main function implements Karatsuba's algorithm for fast
79+
* multiplication
80+
* @param str1 the input string 1
81+
* @param str2 the input string 2
82+
* @returns the multiplicative number value
83+
*/
84+
int64_t karatsuba_algorithm(std::string str1, std::string str2) {
85+
int64_t len1 = str1.size();
86+
int64_t len2 = str2.size();
87+
int64_t n = std::max(len1, len2);
88+
std::string zero = "0";
89+
if (len1 < len2) {
90+
for (int64_t i = 0; i < len2 - len1; i++) {
91+
zero += str1;
92+
str1 = zero;
93+
}
94+
} else if (len1 > len2) {
95+
zero = "0";
96+
for (int64_t i = 0; i < len1 - len2; i++) {
97+
zero += str2;
98+
str2 = zero;
99+
}
100+
}
101+
if (n == 0) {
102+
return 0;
103+
}
104+
if (n == 1) {
105+
return (str1[0] - '0') * (str2[0] - '0');
106+
}
107+
int64_t fh = n / 2; // first half of string
108+
int64_t sh = (n - fh); // second half of string
109+
110+
std::string Xl = str1.substr(0, fh); // first half of first string
111+
std::string Xr = str1.substr(fh, sh); // second half of first string
112+
113+
std::string Yl = str2.substr(0, fh); // first half of second string
114+
std::string Yr = str2.substr(fh, sh); // second half of second string
115+
116+
// Calculating the three products of inputs of size n/2 recursively
117+
int64_t product1 = karatsuba_algorithm(Xl, Yl);
118+
int64_t product2 = karatsuba_algorithm(Xr, Yr);
119+
int64_t product3 = karatsuba_algorithm(
120+
divide_and_conquer::karatsuba_algorithm::addStrings(Xl, Xr),
121+
divide_and_conquer::karatsuba_algorithm::addStrings(Yl, Yr));
122+
123+
return product1 * (1 << (2 * sh)) +
124+
(product3 - product1 - product2) * (1 << sh) +
125+
product2; // combining the three products to get the final result.
126+
}
127+
} // namespace karatsuba_algorithm
128+
} // namespace divide_and_conquer
129+
130+
/**
131+
* @brief Self-test implementations
132+
* @returns void
133+
*/
134+
static void test() {
135+
// 1st test
136+
std::string s11 = "1";
137+
std::string s12 = "1010";
138+
std::cout << "1st test... ";
139+
assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm(
140+
s11, s12) == 10); // here the multiplication is 10
141+
std::cout << "passed" << std::endl;
142+
143+
// 2nd test
144+
std::string s21 = "11";
145+
std::string s22 = "1010";
146+
std::cout << "2nd test... ";
147+
assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm(
148+
s21, s22) == 30); // here the multiplication is 30
149+
std::cout << "passed" << std::endl;
150+
151+
// 3rd test
152+
std::string s31 = "110";
153+
std::string s32 = "1010";
154+
std::cout << "3rd test... ";
155+
assert(divide_and_conquer::karatsuba_algorithm::karatsuba_algorithm(
156+
s31, s32) == 60); // here the multiplication is 60
157+
std::cout << "passed" << std::endl;
158+
}
159+
160+
/**
161+
* @brief Main function
162+
* @returns 0 on exit
163+
*/
164+
int main() {
165+
test(); // run self-test implementations
166+
return 0;
167+
}

0 commit comments

Comments
 (0)