大数相乘问题

方法I————采用最简单的思路,但可能最复杂的实现
具体思路为:将较大数作为被乘数,较小者作为乘数,逐位相乘得到一结果,并且根据其对应的基位(个十百千等)进行相应的补零,
    将最终的结果放入到结果列表中。
    然后从第一个结果开始,通过将其反转逐位相加得到中间结果,直到加完所有。
    其中难点在于进位的问题,在中途产生进位可以按照一般思路处理,重点在于最后一次迭代,这里产生的进位不会有多一轮循环加上它,
 因而需要判断是否到达了最后一位,如果到达了最后一位,则直接将相加结果加到中间结果字符串上。

具体实现如下:(python版)

c++的字符数组通过指针处理逆序很有优势,但字符串转换感觉没有python这么方便。

def Multiplication_algorithm1(a,b):
    max_num=a if a>=b else b
    min_num=str(b if a>=b else a)

    length=len(min_num)
    list_result=[]

    for i in range(length-1,-1,-1):
        string=str(max_num*int(min_num[i]))+((length-i-1)*'0')
        list_result.append(string)

    result=str(list_result[0])


    for x in range(1,length):#result已经将个位数相乘的作为了结果

        lengthoftemp=len(str(list_result[x]))
        lengthofresult=len(result)
        num=lengthoftemp-lengthofresult

        if num>=0:
            result=num*'0'+result
        else:
            list_result[x]= (-num)*'0' +list_result[x]

        temp_result = ''#临时结果存储
        n=0#判断是否需要进位
        count=1#用来判断是否已经到一组字符串最后两位相加了,到最后两位相加这不需要进位了
        temp1=result[::-1]
        temp2=(list_result[x])[::-1]

        for a,b in zip(temp1,temp2):
            #print(a,b)
            c = int(a) + int(b) + n
            if count==len(temp1):
                temp_result = str(c) + temp_result

            else:
                if c < 10:
                    temp_result =  str(c)+temp_result
                    n=0
                else:
                    temp_num_1 = c % 10
                    n = int(c / 10)
                    temp_result =  str(temp_num_1)+temp_result
            count+=1
        result=temp_result

    return result

 

方法II——逐位相乘改进版

具体思路为,先将每一位进行相乘取和不进位,将对应位相加保存至同一个地方,最后进行进位操作

如:

9  8
  X 2  1
________________
    (9)(8)
(18)(16)
____________
(18)(25)8==2058

具体实现如下(py版):

def Multiplication_algorithml(a,b):
    result=''
    temp_result=[]#用来存放逐位相乘的结果

    max_num=str(a if a>=b else b)[::-1]
    min_num=str(b if a>=b else a)[::-1]

    lengthofmax_num=len(str(max_num))#累乘的次数

    for z in range(lengthofmax_num):
        temp_result.append(int(min_num[0])*int(max_num[z]))

    #用来记录各个位的和
    for x in range(1,len(min_num)):
        for y in range(lengthofmax_num):
            if y<(lengthofmax_num-1):#判断这个位上是否已经有数字了
                temp_result[x+y]=(temp_result[y+x]+(int(min_num[x])*int(max_num[y])))
                y+=1
            else:
                temp_result.append(int(min_num[x])*int(max_num[y]))
                break
    #用来处理进位
    n=0 #用来记录进位
    for i in temp_result:
        if i!=temp_result[-1]:
            mod=int(i+n)%10#记得把进位+i当成一个整体
            n=(int((i+n)/10))
            result=str(mod)+result

        else:
            mod=int(i)+n
            result=str(mod)+result

    return result

方法III--Karatsuba法

Karatsuba算法主要应用于两个大数的相乘,原理是将大数分成两段后变成较小的数位,然后做3次乘法,并附带少量的加法操作和移位操作。

wiki_link   https://en.wikipedia.org/wiki/Karatsuba_algorithm

百度link https://baike.baidu.com/item/karatsuba%E4%B9%98%E6%B3%95/7615272?fr=aladdin

 

具体实现(python版):

def Multiplication_algorithml(a,b):
    max_num=a if a>=b else b
    min_num=b if a>=b else a

    result=Karatsuba(max_num,min_num)
    return result


#适用于两个大数位数差不多且位数都长的情况
def Karatsuba(max_num,min_num):
    if(max_num<10 or min_num<10):
        return max_num*min_num

    lengthofmax=len(str(max_num))
    lengthofmin=len(str(min_num))
    m=0#用来记录乘方个数

    #拆分数字
    #如果数字为偶数位,可以让拆分部分各占一半,如果奇数位,可以考虑让前面的数字多一位
    half=int(lengthofmax/2)
    x1=int(str(max_num)[:lengthofmax-half])
    x2=int(str(max_num)[lengthofmax-half:])
    m =int(lengthofmax- (lengthofmax / 2))
    y1=int(str(min_num)[:lengthofmin-half])
    y2=int(str(min_num)[lengthofmin-half:])

    z0=x1*y1
    z2=x2*y2

    z1=(x1+x2)*(y1+y2)-z0-z2

    result=z0*pow(10,2*m)+z1*pow(10,m)+z2
    return result

 

转载于:https://my.oschina.net/u/3641281/blog/1556869

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值