C++基础算法①——高精度加减法计算
创始人
2024-06-03 09:46:52
0

高精度算法

  • 1.导论
  • 2.高精度+低精度
  • 3.高精度+高精度
  • 4.高精度减法

1.导论

当我们利用计算机进行数值计算,有时候会遇到这样的问题: n!的精确结果是多少?
当n小于30的时候,我们当然可以通过电脑自带的计算器计算出来。但是当我们遇到 100! 的时候就没有办法直接计算出精确的结果。再比如,求两个20000位的数的和。

那怎么解决精度缺失的问题?
高精度算法(High Accuracy Algorithm) 是处理大数字的数学计算方法。

  • 在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几千亿几百亿的大数字。一般这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘,开方等运算。对于非常庞大的数字无法在计算机中正常存储。
  • 于是,将这个数字拆开,拆成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。
  • 高精度算法就是能处理高精度数各种运算的算法,但又因其特殊性,故从普通数的算法中分离,自成一家。
  • 高精度处理,实际上就是模拟法,模拟手算,它的原理与我们用竖式计算时一样的,不过在处理过程中要注意高精度数据的读入、转换储存、数据的计算、结果位数的计算、输出等几个问题。

2.高精度+低精度

有一个很大的数,例如 99999999999999999;一个小的数6666。如何把这两个数加起来呢?

高精度的加法思想

  1. 把大数存到字符串;

  2. 字符串的每个字符数字都通过ASCII转换存到数组,
    注意的是要低位存在数组开头:a[i] = s[len-i-1]-‘0’;

  3. 加法进位的算式:
    ① a[i+1] += a[i]/10;
    ② a[i] %= 10;

  4. 数字溢出,长度+1;

  5. 反向输出结果;

来看下我们怎么做的,以C++语言编程为例子。

#include
#include
using namespace std;
string s1;
int a[1000],b; 
int main(){cin>>s1>>b; // 1.输入数值 

代码中,s1数组存的是大数,b整数存小数。
① 1234 + 66
② 123456 + 99
按照数学加法运算,是先个位数与个位数相加,也就是
① s1[3] + 6
② s1[5] + 9
由上面可知,个位数+个位数的索引下标不一致,会增加编程难度。那可以考虑把数组倒序存储!个位数放到数组开头位置也就是s1[0],那无论数值多大,数组下标都是s1[0] 开始进行加法的。

//	s1存到数组a里面,记得转为整数int len1 = s1.size(); //获取长度for(int i=0;ia[i] = s1[len1-i-1]-'0';} 

因为s1是字符串要通过ASCII码表转成整数,所以要减掉 -‘0’。

好,上面我们已经完成把大数存到数组里了,接着要进行加法运算。

  • 把小数先加到a[0]位置: a[0] +=b; 例如 1234 + 89 =》a[0] = 1323;
  • 接着把新的个位数留在a[0],其他位数进行 进位操作。
a[0+1] += a[0] /10; // a[1] = 3+132 = 135  
a[0] = a[0] % 10; // a[0] = 3
  • 以此类推,更新十位数,其他位数进位操作。
	//3.进行加法运算。a[0]+=b; // 5+9999 10004//4.进位操作for(int i=0;ia[i+1] += a[i] / 10;a[i] = a[i] % 10;}

加法运算后,要考虑到数子溢出的情况; 例如 999 +11 == 1010 多出来了千位数。解决这个问题简单,判断最高位是否不为0,满足条件就再一次进行进位操作!

	//5.考虑到数字溢出 while(a[len1]){a[len1+1] += a[len1]/10;a[len1] %= 10;len1++;} 

最后输出结果,记得要反向,因为前面我们a[0] 是最低位,输出从左到右是高位到低位的。

	//6.反向输出for(int i=len1-1;i>=0;i--){cout<

高精度+低精度完整代码如下:

#include
#include
using namespace std;
string s1;
int a[1000],b; 
int main(){cin>>s1>>b;
//	s1存到数组a里面,记得转为整数int len1 = s1.size();for(int i=0;ia[i] = s1[len1-i-1]-'0';} //3.进行加法运算。a[0]+=b; // 5+9999 10004//4.进位操作for(int i=0;ia[i+1] += a[i] / 10;a[i] = a[i] % 10;}//5.考虑到数字溢出 if(a[len]){len++;} //6.反向输出for(int i=len1-1;i>=0;i--){cout<

在这里插入图片描述


3.高精度+高精度

跟上面步骤相似。

高精度的加法思想:

  1. 把大数存到字符串;
  2. 字符串的每个字符数字都通过ASCII转换存到数组,
    注意的是要低位存在数组开头:a[i] = s[len-i-1]-‘0’;
  3. 获取最大的数长度:max(len1,len2) ;
  4. 加法进位的算式:
    ① a[i+1] += a[i]/10;
    ② a[i] %= 10;
  5. 数字溢出,长度+1;
  6. 反向输出结果;
#include
#include
using namespace std;
string s1,s2;
int a[10000],b[10000],c[100001];
int main(){
//	1.输入值,长度 cin>>s1>>s2;  int len1 = s1.size();int len2 = s2.size(); 
//	2.把字符转为整数存到数组
//  注意要个位存到数组开头 for(int i=0;ia[i] = s1[len1-i-1]-'0';} for(int i=0;ib[i] = s2[len2-i-1]-'0';}

两个大数都要存到字符串,再转为整数。然后按照位数,数组下标依次相加,也就是a[i]+b[i]。加到什么时候停止是由长度最大的数决定的,所以我们要求最大的数长度,再进行加法。

//	3.获取最大的数。 int len = max(len1,len2);// 对各个位数进行相加并把最新的值存到输出C里面。for(int i=0;ic[i]=a[i]+b[i];}

通过c[i] = a[i]+b[i]; 可能会出现例如 c[0] = 11,大于10的情况,需要进位!

	//4.进位for(int i=0;ic[i+1] += c[i]/10;c[i] %= 10; }

还是一样的,进位后考虑到溢出问题,然后反向输出

	//6.考虑到数字溢出 if(a[len]){len++;} //7.反向输出 for(int i=len-1;i>=0;i--){cout<

高精度+高精度完整代码:

#include
#include
using namespace std;
//12345647899513131515656
//54213213
string s; // 大数 
int a[10000],b; // b代表小数 
int main(){
//	1.输入值cin>>s>>b;
//	2.如何把s转为整数存到数组int len = s.size(); //字符串长度
//	3.分别把每一个字符存到整数数组里面!for(int i=0;i//a[0]存最低位(个位数),把字符转为数字 a[i] = s[len-i-1]-'0'; }	
//	4.两个数相加,a[0]+ba[0] += b; //9+1111 a[0]=1120 //5.进位 for(int i=0;ia[i+1] += a[i] / 10; //进位 a[i] %= 10; //本位 }//6.考虑到数字溢出 if(a[len]){len++;} //7.反向输出 for(int i=len-1;i>=0;i--){cout<

在这里插入图片描述


4.高精度减法

减法是这样要求的,当两数相减<0,要输出带负 ‘-’ 号!

高精度减法的思想:

  1. 输入两个大数;

  2. 判断大小,固定s1恒大于s2:

  3. 获取长度;

  4. 字符变整数:a[i] = s1[len1-i-1]-‘0’;

  5. 减法运算:
    ① if(a[i]
    a[i+1]–; //上位–
    a[i]+=10; // 本位+10
    }
    ② c[i] = a[i]-b[i];

  6. 去除前导零;

  7. 反向输出;

看下,输入值,输入第一个代表减数,第二个代表被减数;我们知道减法是会有负数情况的,所以要考虑到减数<被减数情况。也就是 减数长度 < 被减数长度 或者 长度相等情况 减数值 < 被减数值。那我们就输出 ‘-’ 号,和交换两个的值。永久实现减数 恒大于 被减数!!!

#include
#include
using namespace std;
string s1,s2;
int a[10000],b[10000],c[10000];
int main(){
//	1.输入值cin>>s1>>s2;
//	2.判断大小,固定s1恒大于s2 if(s1.size()swap(s1,s2); //交换值cout<<"-";} 
//	3.获取长度int len1 = s1.size(); int len2 = s2.size();  
//	4.字符变整数for(int i=0;ia[i] = s1[len1-i-1]-'0';} for(int i=0;ib[i] = s2[len2-i-1]-'0';} 

转为整数存到数组里面后,进行减法运算,根据减法规则,不够减的要借位+10,被借位的要减1。例如 1234 - 66。 如果 a[0] - b[0] < 0,就要借位+10,也就是 a[0] + 10 后再减 b[0];然后被借位 a[0+1]–;

	//5.减法运算 for(int i=0;iif(a[i]a[i+1]--; //被借位-- a[i]+=10; // 本位+10 }c[i] = a[i]-b[i];  //相减结果存到数组c} 

要注意的是:123 -120 = 003,前面的零要消除掉。然后再反向输出。

	//6.去除前导零while(c[len1-1]==0 && len1>1){len1--;} //7.反向输出for(int i=len1-1;i>=0;i--){cout<

高精度减法完整代码:

/*
高精度减法的思想1.输入大数; 2.判断大小,固定s1恒大于s2:if(s1.size()1){len1--;} 7.反向输出;
*/
#include
#include
using namespace std;
string s1,s2;
int a[10000],b[10000],c[10000];
int main(){
//	1.输入值cin>>s1>>s2;
//	2.判断大小,固定s1恒大于s2 if(s1.size()swap(s1,s2); //交换值cout<<"-";} 
//	3.获取长度int len1 = s1.size(); int len2 = s2.size();  
//	4.字符变整数for(int i=0;ia[i] = s1[len1-i-1]-'0';} for(int i=0;ib[i] = s2[len2-i-1]-'0';} //5.减法运算 for(int i=0;iif(a[i]a[i+1]--; //上位-- a[i]+=10; // 本位+10 }c[i] = a[i]-b[i]; } //6去除前导零while(c[len1-1]==0 && len1>1){len1--;} //7.反向输出for(int i=len1-1;i>=0;i--){cout<

在这里插入图片描述

相关内容

热门资讯

清朝有很多有名的历史人物,能给... 清朝有很多有名的历史人物,能给大家说几个清朝的历史人物吗?林则徐,张之洞,乾隆皇帝,曾国藩,朱耷,这...
曹丕的“太子四友”指的是谁 曹丕的“太子四友”指的是谁首先说,曹丕这四个,陈群司马懿是顶级的谋士和政治家,吴质有些小聪明,朱铄不...
在这次遇难者中存在了几名幸存者... 在这次遇难者中存在了几名幸存者。这句话是不是逻辑错误这句话的逻辑没有问题,有问题的是用词不当。遇难者...
在中国古代,有许多充满哲学智慧... 在中国古代,有许多充满哲学智慧的成语典故、寓言故事,如...在中国古代,有许多充满哲学智慧的成语典故...
清澈的意思是什么,… 清澈的意思是什么,…清净而明澈清而透明【造句】看着他清澈而又天真的眼眸,我的心久久不能平静……
蚂蚁森林合种爱情树一方退出怎么... 蚂蚁森林合种爱情树一方退出怎么找回来两个人合种的爱情树,我退出来,我怎么再次加入进去继续合作那个树?...
有好看的古代修炼小说推荐吗? 有好看的古代修炼小说推荐吗?古代重生穿越修炼......让我帮你找一下这些古代修炼的小说,找到这些类...
女主重生爱上前世辜负的人 女主重生爱上前世辜负的人重生我是你正妻渣女重生之竹马重生之弃渣重生之夫君可欺重生之换我疼你重生妇归来...
华胥引有广播剧吗 华胥引有广播剧吗现有的华胥引的广播剧是忆语广播剧社出品的,只有十三月和杯(这个是错字,请无视,居然输...
选文韩麦尔先生在说了,我的朋友... 选文韩麦尔先生在说了,我的朋友们我就要离开你们呢了,再见了银头鲑鱼tj75rt6yturdrruv ...
中通快递从北京保定市到广东揭阳... 中通快递从北京保定市到广东揭阳普宁要多久?中通快递从北京保定市到广东揭阳普宁要多久?从北京到广东需要...
关于离婚悲伤的歌曲 关于离婚悲伤的歌曲关于离婚悲伤的歌曲林俊杰《可惜没如果》 张靓颖《我走以后》 金志文《流着泪说分手》...
形容文笔差怎么说啊? 形容文笔差怎么说啊?哥哥姐姐,麻烦问下,我是做文员的,形容文案方面的工作很差应该怎么说啊?粗鄙怎么样...
我想做未婚妈妈,可行吗? 我想做未婚妈妈,可行吗?没关系吧?我同学好多他们妈妈都是30岁以后省得他们,都没事啊,但是如果你自己...
如何在两个excel表格里筛选... 如何在两个excel表格里筛选出重复的名字如何在两个excel表格里筛选出重复的名字1、电脑打开EX...
且试天下 哪些小说是用白绫做武... 且试天下 哪些小说是用白绫做武器的?神雕侠侣吖- -..小龙女一开始就是用白绫的聊斋 辛十四娘嘿嘿~...
自带高冷体质,笑起来温暖又治愈... 自带高冷体质,笑起来温暖又治愈的星座,你了解吗?虽然天生高冷体质,但是笑起来特别的温暖治愈的新作用天...
火星未解之谜 火星未解之谜多列举一些,每个事例最好长一点,谢啦~“火星人脸”, “地表被水冲击河道”,“原始大气和...
我是1991年10月4号生的,... 我是1991年10月4号生的,是什么星座啊有的说是处女座有的说是天平座,糊涂了,到底是什么啊很负责任...
梦见白狐狸,然后当时我骑着自行... 梦见白狐狸,然后当时我骑着自行车,我想躲开它,他很凶的的追赶我,最后它向我扑了过来,然后我就醒乐.你...