[知识点] 6.3 高精度计算

Posted jinkun113

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[知识点] 6.3 高精度计算相关的知识,希望对你有一定的参考价值。

总目录 > 6 数学 > 6.3 高精度计算

前言

同样也是接触甚早同时也使用很多的一个内容,但许多时候手头没有模板又不想打。。所以是时候来个正儿八经的模板了!

子目录列表

1、概念

 

 

6.3 高精度计算

1、概念

众所周知,int 类型变量是 2 ^ 31(10 ^ 9) 数量级的,long long 类型变量是 2 ^ 63(10 ^ 18) 数量级的,而如果我们需要更高位数的计算呢?这时候就需要用到高精度计算。

高精度计算(Arbitrary-Precision Arithmetic),是指运用一些算法结构来支持位数更高的数之间的运算。其本身难度不高,但代码细节多,实现方式也有诸多不同,但万变不离其宗的是,其本质均是通过按照数位对数进行拆分计算。下面进行介绍。

 

2、数位存储

① 顺序存储

一般情况下,我们对数的存储便是简单的一个萝卜一个坑 —— 一个 int 类型的 a 表示一个数;一个 int 类型的数组 b[100] 表示 100 个数。因为数据类型本身存在范围,在需要高位数运算时,我们大可不必将整个数全部塞入一个变量中。

我们声明两个 int 类型的数组 a, b,a[i], b[i] 分别表示第一、二个数的从低到高的第 i 位(不使用 a[0], b[0])。再声明一个 int 类型的数组 c,用来存储结果。以相加为例,如图所示:

技术图片

只要学过竖式计算,这个计算过程应该不需多言。从最低位,即第 6 位开始按位相加,如果两个数相加大于 10,则向前进一位。具体到实现的话,即如果 a[i] + b[i] >= 10,则 c[i] = a[i] + b[i] - 10, c[i - 1]++;以此类推,直到计算完最高位,计算结束,如图所示,c 存储结果。

② 逆序存储

上述顺序存储很方便,却并非最为符合逻辑的存储方法。原因有三:

> 首先我们的所有计算都是从个位开始,而使用顺序存储,相当于从最大的下标开始计算,从逻辑上看是相反的,不过这还无伤大雅;

> 上述例子是两个数位数相等,而如果不等,假设 b 的位数为 4 位,直接从第 1 位存储显然是没有对齐各个位置的,则还需要加上移位的操作,使第二个数从第 3 位(即两者位数差 + 1)存储,不过这依旧是可以解决的;

> 最重要的一点是,如果我们的计算结果的位数高于这两个数,更高位的数何去何从?这一点在加减法上问题不大,因为数组还有一个下标 0,可以用来保存进借位结果,但是乘法就不是一个位置能解决的了。

避免上述大大小小的麻烦,逆序存储才是正解。以 762 * 2351 为例,如图所示:

技术图片

a[i], b[i], c[i] 分别表示第一、二个数和结果数的从高到低的第 i 位。可以看到,在乘法运算中结果位数可以超出很多,使用逆序存储,可以肆无忌惮地向后进位。同时,完全无需考虑两个数位数不同的情况。最后,将 c 所存储的内容逆序输出,即 1791462,为最终结果。

③ 多位存储

 

3、四则运算

① 高精度加法

在上述介绍顺序存储时,已经有所提及了,加上本身也没太多难度,也就不再介绍了。

代码:

 

② 高精度减法

在高精度加法的基础上,需要考虑结果为负数的情况。在计算之前就要判断这个情况,如果减数更大,我们可以将减数与被减数对调相减,最后在结果之前加入负号即可,因为 a - b = -(b - a)。先判断减数是否大于被减数,如果减数位数更高,则显然大于;如果位数更低,则小于;如果位数相等,则需从最高位逐位判断,任意一位减数大于被减数对应位时,说明减数更大。

代码:

 

③ 高精度乘法

高精度乘法可以分为高精度 * 单精度和高精度 * 高精度两类。

高精度 * 单精度,即第二个数是个普通的 int 类型,那么问题很好想,我们对于第一个数每一位数字乘上这个数即可,然后和加法类似,进行进位。逐位相加最高不会超过 18,所以加法的进位只可能对更高一位产生 +1 的效果;而对于此处的乘法,其相乘结果可能远大于一个十位数,所以要进的位数可能不止一位。以 1337 * 42 为例,如图所示(原网站提供了一个画风很 jk 的图,这里就直接蒯辣):

技术图片

 

 对于个位,7 * 42 = 294,该位保留 294 % 10 = 4,下位进位 290 / 10 = 29(这里 / 表示整除);

对于十位,3 * 42 + 29 = 155,该位保留 155 % 10 = 5,下位进位 155 / 10 = 15;

以此类推,最终结果为 56154。

高精度 * 高精度,本质是相通的,只不过从单精度情况下的一个数的每一位对另一个数相乘变成了两个数的每一位均需要相乘,即 ai * bj * 10 ^ (i + j - 1),也就是说,对于 a[i] * b[j],其结果应该加到 c[i + j - 1] 中。时间复杂度从 O(n) 暴增至 O(n ^ 2)。还是上述的 1337 * 24,还是原网站的图:

技术图片

 

代码:

 

④ 高精度除法

就像加法与乘法相通,减法与除法也是相通的。除法的计算过程可以理解为若干次减法,只不过相比前面,除法应该是四则运算中最麻烦的,不过只要你理解竖式长除法,其实也没什么难度。

代码:

以上是关于[知识点] 6.3 高精度计算的主要内容,如果未能解决你的问题,请参考以下文章

基础知识彻底搞懂float16与float32的计算方式

基础知识彻底搞懂float16与float32的计算方式

高精度计算

『模板 高精度计算』

JAVA计算时实现数字计算结果高精度

js精度计算