Algorithm_Illminated(Part_1)整数乘法(1-3 Karatsuba乘法)

The Integer Multiplication

Problem: Integer Multiplication

Input: 两个n位非负整数,x和y

output: x和y的乘积(product)

The Grade-School Algorithm

​ 为了唤起你的记忆,考虑x = 5678y = 1234相乘的具体例子(所以n = 4)。参见图1.1。该算法首先计算第一个数字和第二个数字的最后一个数字的部分乘积5678 * 4 = 22712。计算这个部分积归结为将第一个输入(x)的每位数字乘以4,并根据需要加上“进位”。接下来,当计算下一个部分积(5678 * 3 = 17034)时,我们做同样的事情,将第二个输入(y)向左移动一个位数字,并乘以第一个输入(x)的每一位数,在结果的末尾有规则地添加“0”。(个位时零个0,十位时一个0,……以此类推)最后一步是把所有部分积加起来。

1

# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2021/2/9 22:24
# @Author : Yu LiXinQian
# @Email : yulixinqian805@gmail.com
# @File : NaiveSolution.py
# @Project : Algorithm_illuminated

print("Two n-digit number:")
print("Please enter 2 numbers:")

x = input("X : ")
x = int(x)
y = input("Y : ")

y_s = [int(y) // (10**i) % 10 for i in range(len(y))]

partial = [y_s[i] * x * 10**i for i in range(len(y_s))]
print("Naive Solution:")
print(y_s)
print(partial)
print(sum(partial))

Can we do better?

Recursive Algorithm

​ 为了了解Karatsuba乘法,让我们重新使用前面的例子,x = 5678y = 1234。我们将执行一系列步骤,与小学算法完全不同,最终得到x y。这些步骤的顺序应该给你留下非常神秘的印象,就像从帽子里拉出一只兔子。我们将解释什么是Karatsuba乘法,以及它的工作原理。现在要理解的关键点是,有一系列令人眼花缭乱的选项来解决像整数乘法这样的计算问题。

​ 首先,为了把x的前半部分和后半部分看作是独立的数字,我们给它们起了名字 a 和 b (所以a = 56,b = 78)。类似地,c和d分别表示12 和 34。

2

​ 接下来,我们将执行一系列操作,只涉及两位数的数字a、b、c、a、n、d,最后以一种神奇的方式将所有项收集在一起,得到x和y的乘积。

  1. a ∗ c = 56 ∗ 12 = 672 a * c = 56 *12 = 672 ac=5612=672

  2. b ∗ d = 78 ∗ 34 = 2652 b * d = 78 * 34 = 2652 bd=7834=2652

  3. ( a + b ) ∗ ( c + d ) = 134 ∗ 46 = 6164 (a + b) * (c + d)= 134 * 46 = 6164 (a+b)(c+d)=13446=6164

  4. 6164 − 672 − 2652 = 2840 6164 - 672 - 2652 = 2840 61646722652=2840

  5. 1 0 4 ∗ 672 + 1 0 2 ∗ 2840 + 2652 = 70066552 10^4 * 672 + 10^2 * 2840 + 2652 = 70066552 104672+1022840+2652=70066552

​ 一般来说,一个偶数 n 位数的数 x 可以用两个n/2位数来表示,其前半部分和后半部分 a 和 b : x = 10 n/2 * a + b ,同样,我们可以写成 y = 10 n/2 * a + b。

3

​ 表达式提出了一种递归方法来相乘两个数字。为了计算乘积x * y,我们计算表达式。四个相关的乘积(a * c,a * d,b * c, b * d) 涉及少于n位数的数,所以我们可以递归地计算每一个。一旦我们的四个递归调用带着它们的答案返回给我们,我们就可以以显而易见的方式计算表达式。我们在下面的伪代码中总结了这个算法,我们将称之为RecIntMult

RecIntMult

Input: 两个n位正整数 x 和 y

Output: x和y的乘积

Assumption: n是2的倍数


if n = 1 then // base case
	compute x · y in one step and return the result
else // recursive case
	a, b := first and second halves of x
	c, d := first and second halves of y
	recursively compute ac := a · c, ad := a · d,
	bc := b · c, a n d bd := b · d
	compute 10^n · ac + 10^(n/2)· (ad + bc) + bd using
	grade-school addition and return the result
# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2021/2/10 10:39
# @Author : Yu LiXinQian
# @Email : yulixinqian805@gmail.com
# @File : RecursiveSolution.py
# @Project : Algorithm_illuminated

print("Two n-digit positive integers x and y.")
print("Assumption : x,y is the power of 2.")

x = int(input("X : "))
y = int(input("Y : "))


def RecIntMult(x1, y1):
    if x1/10 < 1 and y1/10 < 1:
        return x1 * y1
    else:
        n = len(str(x1))
        n2 = n//2
        a, b = divmod(x1, 10**n2)
        c, d = divmod(y1, 10**n2)
        ac = RecIntMult(a, c)
        ad = RecIntMult(a, d)
        bd = RecIntMult(b, d)
        bc = RecIntMult(b, c)
        return ac*10**n+(ad+bc)*10**n2+bd


print(RecIntMult(x, y))

karatsuba Algorithm

​ 是对上述Recursive的改进。保a * c 和 b * d 的递归计算,另一部分原为( a * d + b * c),我们改为:

在这里插入图片描述

老方法进行加总。

Karatsuba

Input: 两个n位正整数 x 和 y

Output: x和y的乘积

Assumption: n是2的倍数


if n = 1 then // base case
	compute x · y in one step and return the result
else // recursive case
	a, b := first and second halves of x
	c, d := first and second halves of y
	compute p := a + b and q := c + d using
	grade-school addition
	recursively compute ac := a · c, bd := b · d, a n d
	pq := p · q
	compute adbc := pq - ac - bd using grade-school
	addition
	compute 10^n· ac + 10^(n/2)· adbc + bd using
	grade-school addition and return the result
# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2021/2/9 23:01
# @Author : Yu LiXinQian
# @Email : yulixinqian805@gmail.com
# @File : KaratsubaSolution.py
# @Project : Algorithm_illuminated

print("Two n-digit positive integers x and y.")
print("Assumption : x,y is the power of 2.")

x = int(input("X : "))
y = int(input("Y : "))


def KaraIntMult(x1, y1):
    if x1/10 < 1 and y1/10 < 1:
        return x1 * y1
    else:
        n = len(str(x1))
        n2 = n//2
        a, b = divmod(x1, 10**n2)
        c, d = divmod(y1, 10**n2)
        ac = KaraIntMult(a, c)
        bd = KaraIntMult(b, d)
        p = a+b
        q = c+d
        pq = p*q
        adbc = pq-ac-bd
        return ac*10**n+adbc*10**n2+bd


print(KaraIntMult(x, y))

ntMult(a, c)
bd = KaraIntMult(b, d)
p = a+b
q = c+d
pq = pq
adbc = pq-ac-bd
return ac
10n+adbc*10n2+bd

print(KaraIntMult(x, y))


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值