在计算机科学中,基本数据类型(如int、float等)的表示范围是有限的。当我们需要处理超出这些范围的大数时,就需要使用高精度算法。本文将通过具体的代码实现,详细解析高精度算法的原理、实现方法及其优缺点分析。

高精度算法的基本概念

高精度算法,又称大数运算,是指处理超过计算机基本数据类型表示范围的数值运算方法。其核心思想是将大数分解为多个小部分(通常是按位或按段),然后模拟人工计算的过程进行运算。

在我们的实现中,我们定义了一个Number类来表示大数:

"""以x - y, x + y, x * y, x / y为例;x, y均为正数,且均为字符串"""
class Number(number):
    def __init__(self,num,cr):
        """将数字的符号和数值分开存储,数值部分用字符串表示,-1为负号,1为正号"""
        self.num = num  #num为字符串
        self.cr = cr

    def print_num(self):
        """结果输出,确定符号和数字"""
        if self.num == '0':
            print(0)
            return
        if self.cr < 0:
            print('-',self.num)
        else:
            print(self.num)

高精度算法的实现

1. 高精度加法

时间复杂度:O(max(m, n)),其中m和n分别是两个操作数的位数。
空间复杂度:O(max(m, n)),用于存储结果。

def add(x,y):
    """高精度加法"""
    xnum = [int(i) for i in x]  #将字符串传为整数
    ynum = [int(i) for i in y]
    xnum = list(reversed(xnum))  #反转数值位数,使个位数位于首位
    ynum = list(reversed(ynum))
    max_len = max(len(xnum),len(ynum))
    xnum += [0] * (max_len - len(xnum))  #补足空缺位置
    ynum += [0] * (max_len - len(ynum))
    z = [0] * (max_len + 1)  #定义相加值的数组,相加最大位数是原数值最大位数加一
    for i in range(max_len):
        z[i] += xnum[i] + ynum[i]
        z[i+1] = z[i] // 10  #超过10进1
        z[i] = z[i] % 10
    z = list(reversed(z))   #反转结果
    z = [str(i) for i in z]   #类型转为字符串
    z = ''.join(z).lstrip('0')   #输出,并删去最高位数的‘0’
    return z

2. 高精度减法

时间复杂度:O(max(m, n)),其中m和n分别是两个操作数的位数。
空间复杂度:O(max(m, n)),用于存储结果。

1)len(x)大于len(y)的情况:

def sub(x,y):  
    """高精度减法(x,y均为正数,len(x)大于len(y))"""
    xnum = [int(i) for i in x]
    ynum = [int(i) for i in y]
    xnum = list(reversed(xnum))
    ynum = list(reversed(ynum))
    ynum += [0] * (len(xnum) - len(ynum))  #最大位数即x的位数
    z = [0] * len(xnum)
    for i in range(len(xnum)):
        z[i] = xnum[i] - ynum[i]
        if z[i] < 0:
            z[i] += 10  #该位数加10,形成正数
            xnum[i+1] -= 1   #向前一位借1
    z = list(reversed(z))
    z = [str(i) for i in z]
    z = ''.join(z).lstrip('0')
    return z

2)补充情况:

def subtract(x,y,z):  #此处x, y, z为Number输入形式
    """ 高精度减法(x和y均为正数),判断x、y大小,为确定sub函数输入形式"""
    xnum = list(x.num)
    ynum = list(y.num)
    if len(xnum) < len(ynum):  #x位数小于y位数,x一定小于y
        z.cr = -1
        z.num = sub(ynum,xnum)
    elif len(xnum) == len(ynum):
        for i in range(len(xnum)):
            if xnum[i] < ynum[i]:  #表明x小于y
                z.cr = -1
                z.num = sub(ynum,xnum)
    else:
        z.num = sub(xnum,ynum)  #符合 1)的情况
    return z

补充:对两个数值进行判断,判断使用高精度加法还是高精度减法:

def pd_sub_add(x,y):  #此处x, y为Number输入形式
    """对于所有x,y,先进行判断,以便确定使用高精度加法还是高精度减法"""
    z = Number(0,0)
    if x.cr < 0 and y.cr < 0:  #判断两个数值符号
        z.cr = -1
        z.num = add(x.num,y.num)
    elif x.cr < 0 and y.cr > 0:
        subtract(y,x,z)  # 注意x, y位置
    elif x.cr > 0 and y.cr < 0:
        subtract(x,y,z)  #注意x, y位置
    else:
        z.cr = 1
        z.num = add(x.num,y.num)
    return z

3. 高精度乘法

时间复杂度:O(m × n),其中m和n分别是两个操作数的位数。
空间复杂度:O(m + n)。

def multiply(x,y):  #此处xy为字符串
    """高精度乘法(x,y均为正数)"""
    xnum = [int(i) for i in x]
    ynum = [int(i) for i in y]
    xnum = list(reversed(xnum))
    ynum = list(reversed(ynum))
    max_len = max(len(xnum),len(ynum))
    xnum += [0]*(max_len - len(xnum))
    ynum += [0]*(max_len - len(ynum))
    z = [0] * (len(xnum) + len(ynum) + 1)  #两个数值相乘后的最大位数为(m + n + 1)
    for i in range(len(xnum)):
        for j in range(len(ynum)):
            z[i+j] += xnum[i] * ynum[j]
            if z[i+j] > 10:  #相乘结果大于10,向前进位
                z[i+j+1] += z[i+j] // 10
                z[i+j] %= 10
    z = list(reversed(z))
    z = [str(i) for i in z]
    z = ''.join(z).lstrip('0')
    return z
def pd_mul(x,y):  #此处x, y为Number输入形式
    """对于所有x,y,先进行判断,以便确定正负号"""
    z = Number(0,0)
    if x.cr < 0 and y.cr < 0:
        z.cr = 1
        z.num = multiply(x.num,y.num)
    elif x.cr < 0 and y.cr > 0:
        z.cr = -1
        z.num = multiply(x.num,y.num)
    elif x.cr > 0 and y.cr < 0:
        z.cr = -1
        z.num = multiply(x.num,y.num)
    else:
        z.cr = 1
        z.num = multiply(x.num,y.num)
    return z

4. 高精度除法

时间复杂度:O(m + n),其中m是被除数的位数,n是要求的小数位数。
空间复杂度:O(m + n)。

def division(x,y,n): 
    """高精度除法(x,y均为正数),n为小数点后位数"""
    xnum = [int(i) for i in x]
    ynum = int(y)
    z = [0] * (len(xnum) + n)  #最大位数需要加上小数点后位数
    xnum += [0] * n  # 补充小数点后位数
    x = 0
    for i in range(len(xnum)):
        temp = x * 10 + xnum[i]  # 临时被除数
        z[i] = temp // ynum  # 商
        x = temp % ynum   # 余数
    z = [str(i) for i in z]
    z1 = z[:len(xnum)-n]  #整数部分
    z2 = z[len(xnum)-n:len(xnum)]  #小数部分
    z1 = ''.join(z1).lstrip('0')  #整数的最高位数删去‘0’,小数部分不需要
    if z1 == '':  # 如果整数位数为空值,即最后只有0
        z1 = '0'
    z2 = ''.join(z2)
    return z1+'.'+z2
def pd_division(x,y,n):  #此处x, y为Number输入形式
    """对于所有x,y,先进行判断,以便确定正负号"""
    z = Number(0,0)
    if x.cr < 0 and y.cr < 0:
        z.cr = 1
        z.num = division(x.num,y.num,n)
    elif x.cr < 0 and y.cr > 0:
        z.cr = -1
        z.num = division(x.num,y.num,n)
    elif x.cr > 0 and y.cr < 0:
        z.cr = -1
        z.num = division(x.num,y.num,n)
    else:
        z.cr = 1
        z.num = division(x.num,y.num,n)
    return z

代入数值运行

a = Number('12',1)
b = Number('43',1)
z = pd_division(a,b,2)  #可自行更换前面四种运算的函数
z.print_num()

高精度算法的优缺点

优点

  1. 无位数限制:可以处理任意大的数字,只受计算机内存限制

  2. 精确计算:避免了浮点数运算的精度损失问题

  3. 灵活性高:可以根据需要调整精度和表示方式

缺点

  1. 计算速度慢:相比硬件支持的整数运算,高精度算法速度较慢

  2. 内存消耗大:需要额外的内存来存储大数

  3. 实现复杂:需要处理各种边界情况和特殊场景

本文提供的代码实现虽然基础,但清晰地展示了高精度算法的核心思想。在实际应用中,可以根据具体需求进行优化和扩展,以满足不同场景下的计算需求。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐