Genellikle büyük sayılar tam sayıların diziler olarak depolanır. Her bir tam sayı bir rakamı temsil eder. Bu yaklaşım, dizinin basit sola kaymasıyla tabanın gücü ile herhangi bir sayıyı çoğaltmanıza izin verir.
İşte (hatalar içerebilir) benim liste tabanlı bir uygulamasıdır:
def normalize(l,b):
over = 0
for i,x in enumerate(l):
over,l[i] = divmod(x+over,b)
if over: l.append(over)
return l
def sum_lists(x,y,b):
l = min(len(x),len(y))
res = map(operator.add,x[:l],y[:l])
if len(x) > l: res.extend(x[l:])
else: res.extend(y[l:])
return normalize(res,b)
def sub_lists(x,y,b):
res = map(operator.sub,x[:len(y)],y)
res.extend(x[len(y):])
return normalize(res,b)
def lshift(x,n):
if len(x) > 1 or len(x) == 1 and x[0] != 0:
return [0 for i in range(n)] + x
else: return x
def mult_lists(x,y,b):
if min(len(x),len(y)) == 0: return [0]
m = max(len(x),len(y))
if (m == 1): return normalize([x[0]*y[0]],b)
else: m >>= 1
x0,x1 = x[:m],x[m:]
y0,y1 = y[:m],y[m:]
z0 = mult_lists(x0,y0,b)
z1 = mult_lists(x1,y1,b)
z2 = mult_lists(sum_lists(x0,x1,b),sum_lists(y0,y1,b),b)
t1 = lshift(sub_lists(z2,sum_lists(z1,z0,b),b),m)
t2 = lshift(z1,m*2)
return sum_lists(sum_lists(z0,t1,b),t2,b)
sum_lists
ve sub_lists
döner normalize edilmemiş sonuç - tek haneli taban değerinden büyük olabilir. normalize
işlevi bu sorunu çözdü.
Tüm işlevler, rakamların ters sırayla alınmasını bekler. Örneğin, taban 10'daki 12, [2,1] olarak yazılmalıdır. geliştirmek böl-ve dört yerine 3 özyinelemeli çağrılar yaparak çarpma algoritmasını ele geçirmek Karastuba Çarpmanın hedeftir 9987654321.
» a = [1,2,3,4,5,6,7,8,9]
» res = mult_lists(a,a,10)
» res.reverse()
» res
[9, 7, 5, 4, 6, 1, 0, 5, 7, 7, 8, 9, 9, 7, 1, 0, 4, 1]
Tabii ki özyineleme durmuyor: özyineyi durduran durum nerede? – neurino
Emin değilim, belki kullanarak x0, x1 = divmod (x, bm) 'daha hızlı olacaktır. – utdemir
@neurino, ilk satırda, ifadenin geri dönüşü varsa. – utdemir