我需要理解为什么我的代码会给出错误的答案。任务是通过分而治之的方法创建二进制乘法。我找到了一些描述这类问题的论文: wikibooks algorithms UTSC paper (page 4)
这是我的Python代码(3.5.2)
def add(A, B):
a_str = "".join([str(a) for a in A])
b_str = "".join([str(b) for b in B])
bin_a = int(a_str, 2)
bin_b = int(b_str, 2)
return [int(a) for a in str(bin(bin_a + bin_b))[2:]]
def add_n(*args):
if len(args) <= 1:
return args[0]
bin_sum = [0]
for num in args:
bin_sum = add(bin_sum, num)
return bin_sum
def shift(A, n):
if n <= 0:
return A
a_str = "".join([str(a) for a in A])
bin_a = int(a_str, 2)
bin_a = bin(bin_a << n)
return [int(a) for a in str(bin_a)[2:]]
def lfill(A, n):
return [0] * (n - len(A)) + A
def multiply(A, B):
n = len(A)
half = n // 2
if n <= 1:
return [A[0] * B[0]]
xl, xh = A[:half], A[half:]
yl, yh = B[:half], B[half:]
a = multiply(xh, yh)
b = multiply(xh, yl)
c = multiply(xl, yh)
d = multiply(xl, yl)
b = add(b, c)
a = shift(a, n)
b = shift(b, half)
return add_n(a, b, d)
有问题的测试1:
A = [1, 1, 1, 1]
B = [0, 1, 0, 0]
result: [1, 1, 1, 1, 0]
real result: [1, 1, 1, 1, 0, 0]
有问题的测试2:
A = [1, 1, 1, 1]
B = [0, 0, 0, 1]
result: [1, 1, 1, 1, 0, 0, 0]
real result: [1, 1, 1, 1]
测试2的值跟踪:
n half
Before Shift [2, 1]: a: [1] b:[1]
After Shift: a: [1, 0, 0] b:[1, 0]
Before Shift [2, 1]: a: [0] b:[0]
After Shift: a: [0] b:[0]
Before Shift [2, 1]: a: [1] b:[1]
After Shift: a: [1, 0, 0] b:[1, 0]
Before Shift [2, 1]: a: [0] b:[0]
After Shift: a: [0] b:[0]
Before Shift [4, 2]: a: [1, 1, 0] b:[1, 1, 0]
After Shift: a: [1, 1, 0, 0, 0, 0, 0] b:[1, 1, 0, 0, 0]
所以,正如你所看到的那样,问题在于零的数量,但是从不确定的情况来看它是不同的。此代码不适用于所有未配对长度的二进制文件,但它不是问题,因为它可以很容易地规范化。
答案 0 :(得分:0)
正确的乘法函数:
def multiply(A, B):
n = len(A)
half = n // 2
if n <= 1:
return [A[0] * B[0]]
xl, xh = A[:half], A[half:]
yl, yh = B[:half], B[half:]
a = multiply(xh, yh)
b = multiply(xh, yl)
c = multiply(xl, yh)
d = multiply(xl, yl)
b = add(b, c)
d = shift(d, n)
b = shift(b, half)
return add_n(a, b, d)
答案 1 :(得分:-1)
def divide_conquer_mul(num1 , num2):
#base Case for Reccursion
if len(str(num1)) == 1 or len(str(num2)):
return num1 * num2
#length of the multiplier & multiplicand
num1 = str(num1)
num2 = str(num2)
len_num1 = len(num1)
len_num2 = len(num2)
# ...and their 'ceil' halves used for combining parts
nby2 = len_num1//2 + 1 if len_num1 % 2 == 1 else len_num1//2
mby2 = len_num2//2 + 1 if len_num2 % 2 == 1 else len_num2//2
# halving multiplier and multiplicand into a,b and c,d...this where we are getting the pairs
# using 'floor' halves of lengths
a , b = num1[ : len_num1 // 2] , num1[len_num1 // 2 : ]
c , d = num2[ : num2 // 2] , num2[num2 // 2 : ]
# recursively multiply ac, ad, bc and bd...this is where we multiply
#the pairs form from the step above
ac , ad = divide_conquer_mul(int(a) , int(c)) , divide_conquer_mul(int(a) , int(d))
bc , bd = divide_conquer_mul(int(b) , int(c)) , divide_conquer_mul(int(b) , int(d))
# combine adding zeros and return.... this is where summation addition of zeros occur
summation = ac * 10**(nby2 + mby2)
summation += ad * 10**(nby2)
summation += bc * 10**(mby2)
summation += bd
return summation
if __name__ == "__main__":
x = divide_conquer_mul(981 , 1234)
print(x)