了解向量乘法

时间:2017-07-03 03:33:18

标签: c++ algorithm vector

我必须通过在c ++中使用向量来执行乘法,因此例如要将数字乘以123和528,我必须将每个数字存储在向量中并将它们相乘。我的导师提供了乘法算法。以下段落的第一行可能看起来有点令人困惑,但我想告诉您,我正在尝试重载运算符*以使用向量在两个数字之间执行乘法。

ubigint :: operator *中的乘法通过分配一个新向量来进行,该向量的大小等于其他两个操作数的大小之和。如果u是大小为m的向量而v是大小为n的向量,则以O(mn)速度,在一个参数上执行外循环,在另一个参数上执行内循环,将新的部分乘积添加到产品p就像你手工做的那样。该算法可以用数学方法描述如下:

p ←Φ   
for i ∈ [0, m):  
 c ← 0  
   for j ∈ [0, n):  
     d ← p_{i+ j} + u_iv_j + c  
     p_{i+ j} ← d % 10  
     c ← ceil(d÷10)  
  p_{i+n} ← c  

注意,区间[a,b)指的是集合{x |a≤x< b},即包括但不包括b的半开间隔。同样,C ++中的一对迭代器绑定了一个区间。

问题是我不能安静地理解这个算法是如何工作的。例如,什么是u_iv_j?。任何人都可以解决这个问题吗?

1 个答案:

答案 0 :(得分:2)

将您的算法视为如何乘以大数字的正式描述:

for i ∈ [0, m):                  # For every digit of the first number
   c ← 0                         # Initialize the carry
   for j ∈ [0, n):               # For every digit of the second number
     d ← p_{i+j} + u_i * v_j + c # Compute the product of the digits + carry + previous result
     p_{i+j} ← d % 10            # extract the lowest digit and store it
     c ← ceil(d÷10)              # carry the higher digits
 p_{i+n} ← c                     # In the end, store the carry in the
                                 # highest, not yet used digit

我遗漏了一些细节(操作顺序......),但我可以在必要时添加它们。

编辑:为了澄清我的意思,我将展示代码对56 * 12的作用: p初始化为0

i = 0:                       # Calculate 6 * 12
  carry = 0
  j = 0:                     # Calculate 6 * 2
    d = p{0} + 6 * 2 + carry # == 0 + 12 + 0
    p{0} = d % 10            # == 2
    carry = ceil(d/10)       # == 1
  j = 1:                     # Calculate 6 * 1 + carry
    d = p{0} + 6 * 1 + carry # == 0 + 6 + 1
    p{1} = d % 10            # == 7
    carry = ceil(d/10)       # == 0
  p{2} = carry               # == 0
i = 1:                       # Calculate 5 * 12
  carry = 0
  j = 0:                     # Calculate 5 * 2
    d = p{1} + 5 * 2 + carry # == 7 + 10 + 0
    p{1} = d % 10            # == 7
    carry = ceil(d/10)       # == 1
  j = 1:                     # Calculate 5 * 1
    d = p{2} + 5 * 1 + carry # == 0 + 5 + 1
    p{2} = d % 10            # == 6
    carry = ceil(d/10)       # == 0
  p{3} = carry               # == 0

对于i = 0,我们计算6 * 12 = 72,对于i = 1,我们计算5 * 12 = 60。

由于5是在第二个数字,我们实际上计算了50 * 12 = 600.现在我们需要添加结果(即72 + 600),这就是为什么我提到前一个值:在第一次运行循环之后,72存储在p,为此添加600,我们只需将本地产品u_i * v_j添加到p{i+j}中的现有值,同时保留进位。