高精度加、减、乘、除算法实现详解

我之前发过一篇关于高精度算法实现的文章(数据结构学习(一):高精度算法),不过有朋友说写的不是很明白,而且实现效率有点低,所以我又找了一篇不错的别人的文章转载了过来,让大家能够对比着看。

原文地址:https://blog.csdn.net/fanyun_01/article/details/79967170

在说高精度加减乘除运算之前,我们先搞明白什么是高精度运算?

       实际上高精度就是说参与运算的数据和运算结果的范围,超出标准数据类型能表示的数据大小范围的运算。这个时候,如果要得到正确的计算结果,显然不能依靠普通方法实现了。而要在普通运算原理的基础上,加以辅助算法来实现超大数据的计算。例如:求两个100位的数据的和,或者计算两个100位的数字乘积。这时就要用到高精度算法了。

    一、高精度加法:

    高精度加法的实现原理:

1、计算结果的位数
358934760892734899共18位
38960302975237462共17位
故结果不会超过19位。
2、将要计算的数字分割成多段,按照顺序排列(这里以0-32767作为每一存储单位存储的数的限制):

(为提高空间利用效率,可以一个存储单位存储多位数。)
3、将两数相加。

4、输出结果。
从高位到低位依次输出。除最高位以外,其他低位上不足4位的要在前面补上0。

5.代码实现如下


 
 
  1. #include<iostream>
  2. #include<cstring>
  3. using namespace std;
  4. int main()
  5. {
  6. string str1,str2;
  7. int a[ 250],b[ 250],len; //数组的大小决定了计算的高精度最大位数
  8. int i;
  9. memset(a, 0, sizeof(a));
  10. memset(b, 0, sizeof(b));
  11. cin>>str1>>str2; //输入两个字符串
  12. a[ 0]=str1.length(); //取得第一个字符串的长度
  13. for(i= 1;i<=a[ 0];i++) //把第一个字符串转换为整数,存放在数组a中
  14. a[i]=str1[a[ 0]-i]- ‘0’;
  15. b[ 0]=str2.length(); //取得第二个字符串长度
  16. for(i= 1;i<=b[ 0];i++) //把第二个字符串中的每一位转换为整数,存放在数组B中
  17. b[i]=str2[b[ 0]-i]- ‘0’;
  18. len=(a[ 0]>b[ 0]?a[ 0]:b[ 0]); //取两个字符串最大的长度
  19. for(i= 1;i<=len;i++) //做按位加法,同时处理进位
  20. {
  21. a[i]+=b[i];
  22. a[i+ 1]+=a[i]/ 10;
  23. a[i]%= 10;
  24. }
  25. len++; //下面是去掉最高位的0,然后输出。
  26. while((a[len] 0)&&(len>1)) len–;
  27. for(i=len;i>= 1;i–)
  28. cout<<a[i];
  29. return 0;
  30. }
  31. //注意:两个数相加,结果的位数,应该比两个数中大的那个数多一位。

二、高精度减法:

  高精度减法的实现原理:

   1.高精度减法相比高精度加法来说,稍微复杂一点,因为减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;在程序实现上用一个变量来存储符号位,用另一个数组存差的绝对值。

   2.实现流程

(1).先比较大小

(2).决定输出符号,为正还是为负

(3).按位减法,并注意处理借位

   3.代码实现如下:


 
 
  1. #include<iostream>
  2. using namespace std;
  3. int compare(string s1,string s2);
  4. int main()
  5. {
  6. string str1,str2;
  7. int a[ 250],b[ 250],len;
  8. int i;
  9. memset(a, 0, sizeof(a));
  10. memset(b, 0, sizeof(b));
  11. cin>>str1>>str2;
  12. a[ 0]=str1.length();
  13. for(i= 1;i<=a[ 0];i++)
  14. a[i]=str1[a[ 0]-i]- ‘0’;
  15. b[ 0]=str2.length();
  16. for(i= 1;i<=b[ 0];i++)
  17. b[i]=str2[b[ 0]-i]- ‘0’;
  18. if((compare(str1,str2)) 0) //大于等于,做按位减,并处理借位。
  19. {
  20. for(i= 1;i<=a[ 0];i++)
  21. {a[i]-=b[i];
  22. if (a[i]< 0) {a[i+ 1]–;a[i]+= 10;}
  23. }
  24. a[ 0]++;
  25. while((a[a[ 0]] 0)&&(a[0]>1)) a[0]–;
  26. for(i=a[ 0];i>= 1;i–)
  27. cout<<a[i];
  28. cout<< endl;
  29. }
  30. else
  31. {
  32. cout<< ’-’; //小于就输出负号
  33. for(i= 1;i<=b[ 0];i++) //做按位减,大的减小的
  34. {b[i]-=a[i];
  35. if (b[i]< 0) {b[i+ 1]–;b[i]+= 10;}
  36. }
  37. b[ 0]++;
  38. while((b[b[ 0]] 0)&&(b[ 0]> 1)) b[ 0]–;
  39. for(i=b[ 0];i>= 1;i–)
  40. cout<<b[i];
  41. cout<< endl;
  42. }
  43. return 0;
  44. }
  45. int compare(string s1,string s2) //比较字符串(两个数)数字的大小,大于等于返回0,小于返回1。
  46. {
  47. if(s1.length()>s2.length()) return 0; //先比较长度,哪个字符串长,对应的那个数就大
  48. if(s1.length()<s2.length()) return 1;
  49. for( int i= 0;i<=s1.length();i++) //长度相同时,就一位一位比较。
  50. {
  51. if(s1[i]>s2[i]) return 0;
  52. if(s1[i]<s2[i]) return 1;
  53. }
  54. return 0; //如果长度相同,每一位也一样,就返回0,说明相等
  55. }

三、高精度乘法实现

    高精度乘法实现原理:

   1.由于数字较大,无法使用简单的数据结构进行存储,选用数组和字符串来存储数字,字符串方便我们对于高位整数的输入,而整形数组的简便有利于每个位数的计算,结合两者优点便可实现高精度乘法。

    2.实现过程:

(1).通过两个字符串输入两个整数

(2).引入两个数组,将每个整数切割存储到数组里面

(3).进行每一位的运算

(4).处理进位

(5).输出结果

  3.代码实现如下:


 
 
  1. #include<iostream>
  2. #include<cstring>
  3. using namespace std;
  4. int main()
  5. {
  6. string str1,str2;
  7. int a[ 250],b[ 250],c[ 500],len; //250位以内的两个数相乘
  8. int i,j;
  9. memset(a, 0, sizeof(a));
  10. memset(b, 0, sizeof(b));
  11. cin>>str1>>str2;
  12. a[ 0]=str1.length();
  13. for(i= 1;i<=a[ 0];i++)
  14. a[i]=str1[a[ 0]-i]- ‘0’;
  15. b[ 0]=str2.length();
  16. for(i= 1;i<=b[ 0];i++)
  17. b[i]=str2[b[ 0]-i]- ‘0’;
  18. memset(c, 0, sizeof©);
  19. for(i= 1;i<=a[ 0];i++) //做按位乘法同时处理进位,注意循环内语句的写法。
  20. for(j= 1;j<=b[ 0];j++)
  21. {
  22. c[i+j -1]+=a[i] b[j];
  23. c[i+j]+=c[i+j -1]/ 10;
  24. c[i+j -1]%= 10;
  25. }
  26. len=a[ 0]+b[ 0]+ 1; //去掉最高位的0,然后输出
  27. while((c[len]== 0)&&(len> 1)) len–; //为什么此处要len>1??
  28. for(i=len;i>= 1;i–)
  29. cout<<c[i];
  30. return 0;
  31. }

四、高精度除法实现

高精度除法实现原理:高精度除法这一块比较复杂,它可以分为两种情况:

第一种情况:高精除以低精,实际上就是对被除的每一位,包括前面的余数都除以除数。

代码实现如下:


 
 
  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. using namespace std;
  5. int main()
  6. {
  7. char a1[ 100],c1[ 100];
  8. int a[ 100],c[ 100],lena,i,x= 0,lenc,b;
  9. memset(a, 0, sizeof(a));
  10. memset(c, 0, sizeof©);
  11. gets(a1); //输入高精度被除数
  12. cin>>b; //输入低精度除数
  13. lena= strlen(a1);
  14. for (i= 0;i<=lena -1;i++)
  15.    a[i+ 1]=a1[i] -48; //将高精度被除数放入a数组
  16. for (i= 1;i<=lena;i++) //按位相除
  17. {
  18. c[i]=(x 10+a[i])/b;
  19. x=(x* 10+a[i])%b;
  20. }
  21.   lenc= 1;
  22. while (c[lenc] 0&&lenc<lena)
  23.   lenc++; //删除前导0
  24. for (i=lenc;i<=lena;i++)
  25. cout<<c[i];
  26. cout<< endl;
  27. return 0;
  28. }

第二种情况:高精除以高精

代码实现如下:


 
 
  1. #include<iostream>
  2. #include<cstring>
  3. using namespace std;
  4. int a[ 100],b[ 100],c[ 100];
  5. int compare(int a[],int b[])//比较a、b,若a>b为1;若a<b为-1;若a=b为0
  6. {
  7. int i;
  8. if(a[ 0]>b[ 0])
  9. return 1;
  10. if(a[ 0]<b[ 0])
  11. return -1;
  12. for(i=a[ 0];i> 0;i–) //从高位到低位比较
  13. {
  14. if(a[i]>b[i])
  15. return 1;
  16. if(a[i]<b[i])
  17. return -1;
  18. }
  19. return 0;
  20. }
  21. void subduction(int a[],int b[])//计算a=a-b
  22. {
  23. int flag;
  24. int i;
  25. flag=compare(a,b);
  26. if(flag 0) //相等
  27. {
  28. a[ 0]= 0;
  29. return;
  30. }
  31. if(flag== 1) //大于
  32. {
  33. for(i= 1;i<=a[ 0];i++)
  34. {
  35. if(a[i]<b[i]) //若不够向上借位
  36. {
  37. a[i+ 1]–;
  38. a[i]+= 10;
  39. }
  40. a[i]-=b[i];
  41. }
  42. while(a[ 0]> 0&&a[a[ 0]] 0)//删除前导0
  43. a[ 0]–;
  44. return;
  45. }
  46. }
  47. int main()
  48. {
  49. char str1[ 100],str2[ 100];
  50. int i,j;
  51. memset(a, 0, sizeof(a));
  52. memset(b, 0, sizeof(b));
  53. memset(c, 0, sizeof©);
  54. cin>>str1>>str2;
  55. a[ 0]= strlen(str1); //a[0]存储串1的位数
  56. b[ 0]= strlen(str2); //b[0]存储串2的位数
  57. for(i= 1;i<=a[ 0];i++)
  58. a[i]=str1[a[ 0]-i]- ‘0’;
  59. for(i= 1;i<=b[ 0];i++)
  60. b[i]=str2[b[ 0]-i]- ‘0’;
  61. int temp[ 100];
  62. c[ 0]=a[ 0]-b[ 0]+ 1;
  63. for(i=c[ 0];i> 0;i–)
  64. {
  65. memset(temp, 0, sizeof(temp));
  66. for(j= 1;j<=b[ 0];j++) //从i开始的地方,复制数组b到数组temp
  67. temp[j+i -1]=b[j];
  68. temp[ 0]=b[ 0]+i -1;
  69. while(compare(a,temp)>= 0) //用减法模拟
  70. {
  71. c[i]++;
  72. subduction(a,temp);
  73. }
  74. }
  75. while(c[ 0]> 0&&c[c[ 0]] 0) //删除前导0
  76. c[ 0]–;
  77. cout<< “商为:”;
  78. if(c[ 0] 0)//输出结果
  79. cout<< 0<< endl;
  80. else
  81. {
  82. for(i=c[ 0];i> 0;i–)
  83. cout<<c[i];
  84. cout<< endl;
  85. }
  86. cout<< “余数为:”;
  87. if(a[ 0] 0) //输出余数
  88. cout<< 0<< endl;
  89. else
  90. {
  91. for(i=a[ 0];i> 0;i–)
  92. cout<<a[i];
  93. cout<< endl;
  94. }
  95. return 0;
  96. }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值