2015-08-24 2 views
2

Je suis en train de mettre en œuvre Karatsuba's Multiplication algorithm en Pythonmise en œuvre Karatsubas en Python algorithme de multiplication

Voici mon code

import math 
# Base 
B=10 
# No. of digits 
n=4 
# Numbers 
x=1234 
y=5678 

def karatsuba(x,y,d): 
    if (x < 10 o r y < 10): 
     return x*y 

    # Partition 
    m=math.floor(d/2) 
    n=math.ceil(d/2) 

    x1=x//B**n 
    x2=x%B**n 

    y1=y//B**n 
    y2=y%B**n 

    a=karatsuba(x1,y1,m) 
    b=karatsuba(x1+x2,y1+y2,m) #Line 25 
    c=karatsuba(x2,y2,n) 

    tot = a*(B**(2*m)) + b*(B**m) + c 

res=karatsuba(x,y,n) 

print('%d * %d = %d' %(x, y, res)) 

Mais comme vous pouvez le voir dans Line 25, lorsque nous effectuons x1+x2 et y1+y2 (en tenant compte x1x2, y1, y2 sont m chiffres) l'une ou l'autre somme peut dépasser m chiffres. Dans ce cas, comment puis-je faire un appel récursif à karatsuba() avec deux nombres ayant un nombre différent de chiffres. Quelqu'un peut-il donner une solution simple à cela.

+0

Je pense que Knuth a suggéré une variante avec soustraction qui évite le débordement, mais je n'ai pas de copie de TAoCP à portée de main. –

Répondre

0

Cela devrait être une implémentation de travail que j'ai faite pour un cours d'algorithmes:

def karatsuba(x, y): 
    if x < 10 or y < 10: 
     return x * y 
    # get longest digits 
    n = max(math.log10(x) + 1, math.log10(y) + 1) 
    # catch where n is odd 
    n -= n % 2 
    bn = B ** (n // 2) 
    x1, x2 = divmod(x, bn) 
    y1, y2 = divmod(y, bn) 
    ac = karatsuba(x1, y1) 
    bd = karatsuba(x2, y2) 
    # caluclate a+b and c + d subtracting already 
    # calculated ac and bd leaving ad + bc 
    adbc = karatsuba(x1 + x2, y1 + y2) - ac - bd 
    # x . y = 10^n ac + 10^n/2 (ad + bc) + bd 
    return ((B ** n) * ac) + bn * adbc + bd 


res = karatsuba(x, y) 

print('%d * %d = %d' % (x, y, res)) 
+0

Pouvez-vous expliquer votre code. Pourquoi avez-vous utilisé $ log_10 (x) $ – Atinesh

+0

@atinesh, il obtient combien de chiffres sont dans chaque x et y.vous pourriez cast à str et obtenir le maximum en fonction de la longueur, mais j'ai trouvé en utilisant log plus vite –

+0

Merci. J'aurais pu le faire avec 'strings' mais cela nécessite une conversion' string' en 'int'. Je l'évitais car le code serait devenu plus désordonné. Je cherchais d'autres alternatives merci pour votre approche. – Atinesh

0

Vous n'avez pas besoin de transmettre la taille des chiffres. Si vous l'avez fait de cette façon, votre algorithme ne fonctionnerait que pour des nombres avec des chiffres égaux dans chaque appel récursif. Au lieu d'entrer uppon dans la fonction calculer le nombre de chiffres des deux nombres n = max(len(str(x)), len(str(y))) alors vous padd le plus petit des x, y avec 0s à la fin des chiffres les plus significatifs un procéder à diviser les deux par n/2.

+0

J'ai vu une fonction 'zfill' pour padd 0 à gauche. Mais cela fonctionne sur les chaînes. – Atinesh