高精度算法详解:实现大数运算的利器(Python)
·
在计算机科学中,基本数据类型(如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()
高精度算法的优缺点
优点
-
无位数限制:可以处理任意大的数字,只受计算机内存限制
-
精确计算:避免了浮点数运算的精度损失问题
-
灵活性高:可以根据需要调整精度和表示方式
缺点
-
计算速度慢:相比硬件支持的整数运算,高精度算法速度较慢
-
内存消耗大:需要额外的内存来存储大数
-
实现复杂:需要处理各种边界情况和特殊场景
本文提供的代码实现虽然基础,但清晰地展示了高精度算法的核心思想。在实际应用中,可以根据具体需求进行优化和扩展,以满足不同场景下的计算需求。
更多推荐


所有评论(0)