高精度整数问题

上传人:痛*** 文档编号:171983144 上传时间:2022-11-30 格式:PPT 页数:28 大小:255.02KB
收藏 版权申诉 举报 下载
高精度整数问题_第1页
第1页 / 共28页
高精度整数问题_第2页
第2页 / 共28页
高精度整数问题_第3页
第3页 / 共28页
资源描述:

《高精度整数问题》由会员分享,可在线阅读,更多相关《高精度整数问题(28页珍藏版)》请在装配图网上搜索。

1、 高精度整数问题 组合数和Catalan的精确计算福州大学04计算机(3)班 王建南 学号:030402332算法与数据结构第二次作业解题报告问题描述 编一个大整数模板类,用来做高精度整数(也就是任意位数的整数)的四则运算,包括 加法(addition)减法(subtraction)乘法(multiplication)除法(division)利用上面设计的大整数模板类精确地计算组合数和Catalan数。大整数的介绍 在某些情况下(如数据加密和科学计算等方面),我们要处理很大的整数,它无法在计算机硬件能直接表示的范围内进行处理。若用浮点数来表示它,则只能近似地表示它的大小,计算结果中的有效数字也

2、受到限制(如C+中的Double类型有效位只有15位)。若要精确地表示大整数并在计算结果中要求精确地得到所有位数上的数字,就必须用软件的方法来实现大整数的算术运算。需要解决的问题 大整数的表示 在利于编程实现,同时便于提高运算效率的基础上选择数据结构。这个主要是考查数据结构。我们将会发现,在数据结构上的一个小改进对效率的提高有时会有很大帮助的。而数据结构在一定程度上是可以弥补算法的不足的。大整数的运算 利用所选的数据结构,正确、高效地实现整数的四则运算。这主要考查算法。我们可以看到算法的选择对程序的效率是有绝对影响的。算法是决定程序效率的根本。大整数的表示 由于大整数的位数太多,我们首先要做的

3、是把它“拆”开来,放在若干个地方,然后建立不同存储地址之间的联系。很明显,线性数组(或者说是线性表)是首选。下面的存储方式很直观也是最容易想到的。对于大整数1112223334445 我们可以用一维数组来表示:数组下标:存储数据:012 3 4 5 6 7 8 9 1011121112 2 2 3 3 3 4445进位没有存放的位置大整数的表示但我们可以发现这种表示方法的一个不足之处:计算这个大整数加上9000000000000的结果。如果用前面的方式存储,我们会发现进位没有地方存放了。数组下标:大整数一:大整数二:结果:1为什么会出现这种情况?原因在于我们把大整数的高位存放在数组的下标小的位

4、置。而解决这个问题的方法也很简单,就是把整数反过来存放。0 1 2 3 4 5 6 7 8 9 1011121 1 1 2 2 2 3 3 3 44459 0 0 0 0 0 0 0 0 0 0001 1 1 2 2 2 3 3 3 4445这个进位可以通过扩大数组的方法来存放大整数的表示 另一种表示方式数组下标:大整数一:大整数二:结果:1其实前一种表示方法还会有一个问题。就是高位的对齐,这个我们可以通过减法观察到,这里就不说了。基于以上原因,我们采用线性数组,同时把高位存放在下标大的地方。虽然这样子存放我们看起来不那么直观,但后面我们会看到这种存放方式的好处。012 3 4 5 6 7 8

5、 9 1011125 4 4 4 3 3 3 2 2 21110 0 0 0 0 0 0 0 0 00095 4 4 4 3 3 3 2 2 2110高精度加法运算 在确立了使用线性数组表示的大前提后,我们可以很容易地解决高精度加法。(这里为了简便,我就不用类实现了,同时假设那两个大整数都为正数。)1.初始化数组,数组全部元素置为0 2.用字符串读入大整数,同时以反向存储的方式 存放在数组中 3.进位标志flag置为0。从数组低位开始进行加 法运算。这里只要注意flag的更新就行了。4.反向输出结果高精度加法运算高精度加法举例 这里我们假设我们已读入两个大整数,并且也已经被分别反向存放在数组a

6、和数组b中了。加数a 8 7 4 2 5 9 7 80 0 加数b 4 8 3 1 4 8 5 1 9 0 结果c 2 6 8 3 9 7 3 00 1 进位e 1 1 0 0 0 1 1 1 1 0 上面的过程表示为 87952478+915841384=1003793862减法亦可用相同的方法实现,只是现在标志换成借位标记而已。前面补0的原因是为了对齐高精度加、减法小结及其改进我们首先要明确的一点是,选择线性数组及反向存储的方式并不是偶然的。我们可以列一个竖式,用手工模拟854+87的加法就会理解为什么要这样子处理了。而我们同时会发现,一个数组元素只存储一个位的方式有点浪费,虽然这很合乎我

7、们的习惯。但可不可以通过增加存储位数的方法来提高效率呢?毕竟我们需要的这个一个位计算机只要4个二进制位就可以表示了,而VC给我们分配的一个int却有32位。大整数的运算之加、减法的改进我们来分析只存储一个位的大整数加法是怎样进行的。加数a 8 7 4 2 5 9 7 80 0加数b 4 8 3 1 4 8 5 1 9 0结果c 2 6 8 3 9 7 3 00 1进位e 1 1 0 0 0 1 1 1 1 0设i表示数组第i位数,则ci=(ai+bi+e)%10;e=(ai+bi+e)/10;大整数的运算之加、减法的改进所以我们如果要进行多位存储的话,我们只要把上面的计算式子改成ci=(ai+

8、bi+e)%M;e=(ai+bi+e)/M;其中M为10的n次方,n为规定的位数。如,每个数组元素都存储4个位,则M=10000。这个改进并没有引起程序上大的变动,但它的对运算次数的减少是很有用的。做每个元素存储n位的加法,其加法的次数为只存储一位的1/n。这是因为它增大了存储密度,所以运算速度也随之提升了。高精度加法程序 flag=0;n=min(a的位数,b的位数);M=10000;For(i=0;in|flag;i+)ci=(ai+bi+flag)%M;flag=(ai+bi+flag)/M;习题 四川大学Online Judge 1001和1002 http:/ 第二届福州大学程序设计

9、大赛Fibonacci数列 http:/ 我们先来看一个小整数乘以大整数的乘法运算是如何进行的。我们模拟一下587414251047*56的执行过程。这里为了提高效率,56并没有必要被分成两个位去算,而是利用多位存储的思想来运算。大整数:7 4 0 1 5 2 4 1 4 7 8 5乘数:56进位:39 26 2 5 28 14 23 7 23 41 48 32 3 0结果:2 3 6 8 5 0 8 9 1 5 9 8 2 3所以乘法的最后结果就是32895198058632这里的关键就是进位不一定是一位的。其原理和加法多位存储的运算是一样的。高精度乘法现在我们来看看大整数乘以大整数是怎样进

10、行的。还是先做手工模拟一下516541*4845412是怎么算的。我们发现它的原型就是先进行小整数乘以大整数,再把它们的和加起来的过程。其根本思想就是:设两个大整数分别为a,b(都已反向存储了)。将b按10进制展开,b=b0+10*b1+100*b2+bn*10n。其中bi为小于10的非负整数。则a*b=a*b0+a*b1*10+a*b2*100+a*bn*10n。而a*bi就是小整数乘以大整数。(后面乘10k,只要进行移位就可以实现了)高精度乘法高精度乘法算法流程如下:读入被乘数s1,乘数s2把s1、s2分成n位一段,转成数值反向存在数组a,b中;记下b的长度mi=0;从b中取出第i位与a相

11、乘,累加到另一数组c中;(注意:累加时错开的位数应是多少位)i+;检测i值:大于m则转,否则转打印结果为什么结果存放在这一位?高精度乘法程序M=10000;p=大整数a的“位数”;/这里的位数是指多位存储时的位数q=大整数b的“位数”;for(i=0;ip;i+)flag=0;for(j=0;j=0)?在R后面加上bj,转4:转7;7.输出商数Q及余数R。高精度除法这里就不给出除法的程序了。但在实现时需要注意1.除法可以反向除也可以正向存储,只要做相应调整就可以2.实现时需要定义一个函数来比较两个大整数的大小,同时要用到大整数减法3.多位存储还是可以运用的。但细节上要小心习题 四川大学Onli

12、ne Judge 1003、1004 北京大学Online Judge 1001 http:/ 求PI的精度值到10000位 求e的精度值到10000位组合数和Catalan的精确计算由于Catalan函数本身是一个组合数再除以一个相对较小的整数,而除法在前面已经提过了。这里我们就只看组合数的精确求值。算法一:C(m,n)=C(m-1,n)+C(m-1,n-1)C(m,0)=1利用上面的递归式,我们可以在O(n*大整数位数)辅助空间的基础上设计出一个只用加法就能算组合数的算法。但我们看出这在实际上是不实际的。当m=10000,n=5000时,辅助空间就要达到4*5000*3009Bytes约5

13、0几M的内存。实际上,它在时间效率上也是很不理想的。组合数和Catalan的精确计算算法二:利用C(m,n)=m!/(n!*(m-n)!)对上式进行化简可变为C(m,n)=m*(m-1)*(m-n+1)/n!在实现上,我们如果先把m*(m-1)*(m-n+1)算出来再去除以n!的话,时间和空间的消耗都是比较大的。我当时的做法是组合数和Catalan的精确计算1.采用多位存储,数组每个元素存储4位2.从m开始乘到(m-n+1)时,每乘一个数k就相就地除以一个数(m-k+1)。这样即可以保证结果还是整数的同时,减慢空间的消耗。3.等乘数或除数够大时才进行相应的计算。如算100*99*50/50!一

14、开始时我们没必要马上就把100乘到结果上去。而是等再乘上99后,再把结果乘上9900。这样可以减少很多次计算。最后我的程序计算C(5000,2500)和C(10000,5000)/50001差不多要1.7S才能出结果。对这个结果还是不大满意。于是我又想了另一种算法。组合数和Catalan的精确计算算法三分析一下算法二,程序运行时间主要花在高精度乘法和高精度除法上。而乘法是必需的,效率也比除法好很多,因此我们的着眼点就变成了,怎么去避免除法或将除法转换成乘法或干脆就将除法去掉。如果能将除法去掉当然是最好的了。但能不能做到呢?答案是可以。还是利用到算法二的那个化简后的式子。别看它挺长的,但我们可以

15、保证,它的计算结果一定是整数。因为组合数本身就是一个整数,没有理由经过化简后就变成带有小数的实数。组合数和Catalan的精确计算利用这点,联想到小学时经常做的分数化简,只要先把分子进行分解,存放在一个数组count中,counti表示分解后因子为i的个数。再将分母也进行分解,但在分解的过程中,每次得到一个因子k,我们只要countk-就可以了。因为m的值不可能太大,而count最大只需o(m)的辅助空间,所以在空间是可行的。在时间效率上,因为避免了除法运算,所以效率上肯定会有大的改进的。利用和算法二一样的一些技巧后,我的程序计算C(5000,2500)和C(10000,5000)/50001只要0.7S就可以得到结果了。总结其实算法三还是可以再做改进的,如可以预先存储一个素数表,便于分解因数。同时因为分解因式后,我们要计算的其实就是aipi其中ai为素数,pi为正整数。这个可以利用二分的方法进行改进的,只要利用我们前面写的模板类。我们看到这题不论在数据结构和算法改进上都有一些小技巧。选择的数据结构要便于编程实现并要能够有效地解决问题,但一般在数据结构方面能做的改进不是很多。而算法就不一样了,它是整个程序的灵魂,在算法上改进的余地一般也是比较大的。我们只有在掌握基本数据结构的基础上,不断地学习、改进算法才能有效地解决这类题目。

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!