实现唐叶乘法算法的Java程序
它是小学数字乘法算法的替代品。更大的数字。 Karatsuba 算法使用分而治之的快速乘法算法由 Anatolii Alexeevitch Karatsuba 于 1960 年开发。首先想到的是它是什么以及为什么设计它。尽管有 3 种方法可以将数字相乘:
- 三年级算法法(Standard-way)
- 递归算法方法
- 唐叶乘法
为什么是 Karatsuba 算法?
设计算法的目标是因为设计空间惊人地丰富。它的时间复杂度如下所示,因为时间复杂度非常重要,有时在面试问题中会被问到。
O(n^log2(3)) time (~ O(n^1.585))
Where n is the number of digits of the numbers multiplying. It is discussed by multiplying two big integer numbers to show internal working step by step. The goal is to reduce the space complexity for which the integer numbers terms will be broken down in such a way to x and y are broken into a set of digits as the logic behind it is divide and conquer. If the numbers are smaller there is no need to multiply, standard mutilation of two integers is preferred.
为了便于理解,算法被标准化为 4 位数字。一个人可以乘以作为集合的数字。
算法步骤:
- 计算起始集 (a*c)
- 开始集之后的计算集可能是结束集(b * d)
- 用结束集计算起始集
- 从步骤 1 中减去步骤 2 中的步骤 3 的值
- Step1得到的数补4个0,step2的值不变,step4得到的值补2个0。
现在让我们提出上述步骤并在进入实施部分之前用插图展示它
插图:
Input: x = 1234, y = 5678
Processing: As per above inputs
x = 1234
y = 5678
a = 12, b = 34
c = 56, d = 78
Step 1: a * c = 172
Step 2: b * d = 2652
Step 3: (a+b)(c+d) = 134 * 36 = 6164
Step 4: 6164 - 2652 - 172 = 2840
Step 5: 1720000 + 2652 + 284000 = 7006652
Output: 7006652
步骤 5 得到的值实际上是在这两个数字“x”和“y”之间进行标准学校乘法得到的乘积。
1720000 + 2652 + 284000 = 7006652
实施: 请注意,不要掌握为该算法制定的公式,而是以这种方式理解它会使它变得更好。
Java
/// Java Program to Implement Karatsuba Algorithm
// Importing Random class from java.util packahge
import java.util.Random;
// MAin class
class GFG {
// Main driver method
public static long mult(long x, long y) {
// Checking only if input is within range
if (x < 10 && y < 10) {
// Multiplying the inputs entered
return x * y;
}
// Declaring variables in order to
// Find length of both integer
// numbers x and y
int noOneLength = numLength(x);
int noTwoLength = numLength(y);
// Finding maximum length from both numbers
// using math library max function
int maxNumLength
= Math.max(noOneLength, noTwoLength);
// Rounding up the divided Max length
Integer halfMaxNumLength
= (maxNumLength / 2) + (maxNumLength % 2);
// Multiplier
long maxNumLengthTen
= (long)Math.pow(10, halfMaxNumLength);
// Compute the expressions
long a = x / maxNumLengthTen;
long b = x % maxNumLengthTen;
long c = y / maxNumLengthTen;
long d = y % maxNumLengthTen;
// Compute all mutilpying variables
// needed to get the multiplication
long z0 = mult(a, c);
long z1 = mult(a + b, c + d);
long z2 = mult(b, d);
long ans = (z0 * (long)Math.pow(10, halfMaxNumLength * 2) +
((z1 - z0 - z2) * (long)Math.pow(10, halfMaxNumLength) + z2));
return ans;
}
// Method 1
// To calculate length of the number
public static int numLength(long n)
{
int noLen = 0;
while (n > 0) {
noLen++;
n /= 10;
}
// Returning length of number n
return noLen;
}
// Method 2
// Main driver function
public static void main(String[] args)
{
// Showcasing karatsuba multiplication
// Case 1: Big integer lengths
long expectedProduct = 1234 * 5678;
long actualProduct = mult(1234, 5678);
// Printing the expected and corresponding actual product
System.out.println("Expected 1 : " + expectedProduct);
System.out.println("Actual 1 : " + actualProduct + "\n\n");
assert(expectedProduct == actualProduct);
expectedProduct = 102 * 313;
actualProduct = mult(102, 313);
System.out.println("Expected 2 : " + expectedProduct);
System.out.println("Actual 2 : " + actualProduct + "\n\n");
assert(expectedProduct == actualProduct);
expectedProduct = 1345 * 63456;
actualProduct = mult(1345, 63456);
System.out.println("Expected 3 : " + expectedProduct);
System.out.println("Actual 3 : " + actualProduct + "\n\n");
assert(expectedProduct == actualProduct);
Integer x = null;
Integer y = null;
Integer MAX_VALUE = 10000;
// Boe creating an object of random class
// inside main() method
Random r = new Random();
for (int i = 0; i < MAX_VALUE; i++) {
x = (int) r.nextInt(MAX_VALUE);
y = (int) r.nextInt(MAX_VALUE);
expectedProduct = x * y;
if (i == 9999) {
// Prove assertions catch the bad stuff.
expectedProduct = 1;
}
actualProduct = mult(x, y);
// Again printing the expected and
// corresponding actual product
System.out.println("Expected: " + expectedProduct);
System.out.println("Actual: " + actualProduct + "\n\n");
assert(expectedProduct == actualProduct);
}
}
}
Product 1 : 85348320
Product 2 : 21726