Python Karatsuba算法适用于小数字,但不适用于大数字,可以';我不明白为什么

Python Karatsuba算法适用于小数字,但不适用于大数字,可以';我不明白为什么,python,algorithm,karatsuba,Python,Algorithm,Karatsuba,我对编程比较陌生,我并不希望在运行时间方面对该算法特别有效,只是尝试复制Karatsuba算法并使其工作 我试过很多数字和小数字(比如y=40004009343254, x=40004001343234)工作正常,当数字的大小增加时(如y=400040093432542343,x=4000400134323432423),算法停止正常工作,并返回类似但不正确的答案 任何可能出错的线索都将不胜感激 注意:此线程不是关于效率,而是关于获得正确的结果。也就是说,有关效率的评论也将得到考虑和赞赏 代码:

我对编程比较陌生,我并不希望在运行时间方面对该算法特别有效,只是尝试复制Karatsuba算法并使其工作

我试过很多数字和小数字(比如y=40004009343254, x=40004001343234)工作正常,当数字的大小增加时(如y=400040093432542343,x=4000400134323432423),算法停止正常工作,并返回类似但不正确的答案

任何可能出错的线索都将不胜感激

注意:此线程不是关于效率,而是关于获得正确的结果。也就是说,有关效率的评论也将得到考虑和赞赏

代码

y = 4000400934325423423
x = 4000400134323432423

def firsthalf(array):
    firsthalf = array[:len(array)/2]
    return firsthalf
def secondhalf(array):
    secondhalf = array[len(array)/2:]
    return secondhalf
def arrayjoint(array):
    jointarray = long(''.join(map(str,array)))
    return jointarray
def karatsuba(x,y):
    if len(str(x)) == 0 or len(str(y)) == 0:
        return "Can't multiply by a NULL value!"
    if x < 10 or y < 10:
        return x * y
    x_array = [long(i) for i in str(x)]
    y_array = [long(i) for i in str(y)]
    firsthalf_xarray = firsthalf(x_array)
    secondhalf_xarray = secondhalf(x_array)
    firsthalf_yarray = firsthalf(y_array)
    secondhalf_yarray = secondhalf(y_array)
    half_size = max(len(secondhalf_yarray), len(secondhalf_xarray))
    firsthalf_x = arrayjoint(firsthalf_xarray)
    secondhalf_x = arrayjoint(secondhalf_xarray)
    firsthalf_y = arrayjoint(firsthalf_yarray)
    secondhalf_y = arrayjoint(secondhalf_yarray)
    sum_x = firsthalf_x + secondhalf_x
    sum_y = firsthalf_y + secondhalf_y
    first = karatsuba(firsthalf_x,firsthalf_y)
    second = karatsuba(sum_x, sum_y)
    third = karatsuba(secondhalf_x,secondhalf_y)
    return first * 10 ** (2 * half_size) + ((second - first - third) * (10 ** half_size)) + third

result = karatsuba(x,y)
result_correct = x*y
result = str(result)
result_correct = str(result_correct)
file = open("result.txt", "w")
file.write(str(result)  + "\n" + str(result_correct))
file.close
y=4000400934325423423
x=4000400134323432423
def上半部分(阵列):
前半部分=数组[:len(数组)/2]
返回上半场
def第二部分(阵列):
secondhalf=数组[len(数组)/2:]
返回下半场
def阵列接头(阵列):
jointarray=long(“”.join(映射(str,数组)))
回程关节软骨
def karatsuba(x,y):
如果len(str(x))==0或len(str(y))==0:
return“不能乘以空值!”
如果x<10或y<10:
返回x*y
x_数组=[str(x)中i的长(i)]
y_数组=[str(y)中i的长(i)]
firsthalf_xarray=firsthalf(x_数组)
secondhalf_xarray=secondhalf(x_数组)
firsthalf\u yarray=firsthalf(y\u数组)
secondhalf\u yarray=secondhalf(y\u阵列)
一半尺寸=最大值(len(secondhalf_yarray),len(secondhalf_xarray))
前半部分_x=阵列接头(前半部分_x阵列)
第二半个_x=阵列接头(第二半个_x阵列)
前半部分y=阵列接头(前半部分y)
后半部分y=阵列接头(后半部分y阵列)
总和=上半部分+下半部分
总和=上半部分+下半部分
first=karatsuba(上半部分x,上半部分y)
第二个=喀拉祖巴(求和x,求和y)
第三个=喀喇通(第二个一半x,第二个一半y)
返回第一个*10**(2个*1/2大小)+(第二个-第一个-第三个)*(10**1/2大小)+第三个
结果=karatsuba(x,y)
结果_correct=x*y
结果=str(结果)
结果正确=str(结果正确)
文件=打开(“result.txt”、“w”)
file.write(str(结果)+“\n”+str(结果正确))
file.close

浮动不是问题,因为Python有bignum

问题是,当输入具有不同的长度时,您会将它们分割到不同的位置,这会破坏Karatsuba算法的代数基础。通过在索引
-half_size
处拆分(即,后半部分有
half_size
位),我们确保
10**half_size
是正确的基数。试试这个:

def digits_to_long(x_array):
    return long(''.join(x_array)) if x_array else 0L


def karatsuba(x, y):
    if x < 10 or y < 10:
        return x * y
    x_array = str(x)
    y_array = str(y)
    half_size = max(len(x_array), len(y_array)) // 2
    firsthalf_x = digits_to_long(x_array[:-half_size])
    secondhalf_x = digits_to_long(x_array[-half_size:])
    firsthalf_y = digits_to_long(y_array[:-half_size])
    secondhalf_y = digits_to_long(y_array[-half_size:])
    sum_x = firsthalf_x + secondhalf_x
    sum_y = firsthalf_y + secondhalf_y
    first = karatsuba(firsthalf_x, firsthalf_y)
    second = karatsuba(sum_x, sum_y)
    third = karatsuba(secondhalf_x, secondhalf_y)
    return first * 10**(2 * half_size) + (
        (second - first - third) * (10**half_size)) + third


import random
for i in range(10000):
    x = random.randrange(10**18)
    y = random.randrange(10**18)
    assert karatsuba(x, y) == x * y
def数字到长度(x数组):
如果x_数组的其他值为0L,则返回long(“”.join(x_数组))
def karatsuba(x,y):
如果x<10或y<10:
返回x*y
x_数组=str(x)
y_数组=str(y)
half_size=max(len(x_数组)、len(y_数组))//2
firsthalf_x=数字长度(x_数组[:-half_大小])
secondhalf\u x=数字长度(x\u数组[-half\u大小:)
firsthalf_y=数字长度(y数组[:-half_大小])
secondhalf\u y=数字长度(y\u数组[-half\u大小:)
总和=上半部分+下半部分
总和=上半部分+下半部分
first=karatsuba(上半部分x,上半部分y)
第二个=喀拉祖巴(求和x,求和y)
第三个=喀喇通(第二个一半x,第二个一半y)
返回第一个*10**(2个*1/2大小)+(
(第二个-第一个-第三个)*(10**半个尺寸))+第三个
随机输入
对于范围(10000)内的i:
x=随机随机随机范围(10**18)
y=随机随机随机范围(10**18)
断言karatsuba(x,y)==x*y

类似但不正确的答案表明,您已经超过了长整数的最大值,因此进入了“长整数”的世界。这是已知的精确到一个固定的小数位数。(我也反对你称之为
40004009343254
一个“小数字”。如果是米,这个数字仍然等于到月球距离的100000倍以上。)@RadLexus根据,python整数的精度是无限的。(与2.7长整数相同)啊,是的,我在
pow
上看到了这个注释:“与内置的
**
运算符不同,
math.pow()
将其两个参数都转换为float类型。”