高级光能
高精度加法
题目描述:
给出两个整数(a、b),计算它们的和。
输入:一行两个整数(1 < a,b < 10^1000)
输出:一行一个整数,表示a+b的和
这是一道经典的高精度加法,首先注意两个整数上限都是1000位,普通的int肯定爆上限(long long也会爆,不用想),所以只能手写。。。
那具体怎么手写呢?
先来分析一下,普通算加法时必须需要列竖式对吧,这种竖式就可以通过编程模拟出来。很简单就能看出,首先我们将两个数的每一位都相加,例如333和666的每一位都相加,得到999。
当然很容易看出,这样做是肯定不够的,我们要处理每一位进位的情况,也就是检测每一位,超过十上一位加一,但这里要处理一个bug。
举个栗子500和500
这里相加得出的结果是1000。。。
那如果我们把500当成数组存且500中的5存在a[0]的话,就只能把1000里的1存在a[-1]了。
等等
a[-1] ?!
好吧,为了避免这种bug,我这里推荐在存的时候倒过来存
也就是说500要这样存:
a[0] a[1] a[2]
0 0 5
然后每次进位就可以存到a[i+1]了,同时答案的长度如果要记录下来的话,这里得加1。当然推荐把加法写成函数。
下面请看我写的实例:
#include <iostream>
#include <cstring>
using namespace std;
#define MAXLEN 1005
string la, lb; // 用字符串输入两个数
int a[MAXLEN], b[MAXLEN], ans[MAXLEN]; // a是第一个数,b是第二个数, ans是和
int len; // 和的长度
void ADD() // 加法函数
{
for (int i = 0; i < len; i++)
{
ans[i] += (a[i] + b[i]); // 每一位相加
if (ans[i] >= 10) // 处理进位
{
ans[i+1]++;
ans[i] -= 10;
}
}
if (ans[len] >= 1) len++; // 如果有最高位进位,长度+1
}
int main()
{
cin >> la >> lb; // 输入
memset(ans, 0, MAXLEN); // 将ans的每一位初始化为零
for (int i = 0; i < la.length(); i++) a[la.length()-i-1] = la[i] - '0'; // 倒着输入第一个数
for (int i = 0; i < lb.length(); i++) b[lb.length()-i-1] = lb[i] - '0'; // 倒着输入第二个数
len = max(la.length(), lb.length()); // 将答案的长度暂定为第一个和第二个数的长度中最长的一个
ADD(); // 加法
for (int i = len-1; i >= 0; i--) cout << ans[i]; // 输出
return 0;
}
高精度减法
高精度减法和高精度加法相比,减法在差为负数时处理的细节更多一点。
中文名
高精度减法
相 比
细 节
判断被减数与减数的大小
算法流程
读入被减数S1,S2
目
录
- 1基本内容
1基本内容
高精度减法 1、和高精度加法相比,减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;在程序实现上用一个变量来存储符号位,用另一个数组存差的绝对值。 2、算法流程: (1)读入被减数S1,S2(字符串); (2)置符号位:判断被减数是否大于减数:大则将符号位置为空;小则将符号位置为“-”,交换减数与被减数; (3)被减数与减数处理成数值,放在数组中; (4)运算: A、取数; B、判断是否需要借位; C、减,将运算结果放到差数组相应位中; D、判断是否运算完成:是,转5;不是,转A; (5)打印结果:符号位,第1位,循环处理第2到最后一位; 3、细节: ▲如何判断被减数与减数的大小:字符串知识 ①(1)首先将两个字符串的位数补成一样(因为字符串的比较是从左边对齐的;两个字符串一样长才能真正地比较出大小):短的在左边补0 k1:=length(s1); k2:=length(s2); if k1>k2 then for i:=1 to k1-k2 do s2:='0'+s2 else for i:=1 to k2-k1 do s1:='0'+s1; (2)接着比较大小:直接比较字符串大小 fh:=''; if s1l1 then p:=true{开始分析数值AB的大小,如果B位数高则B更大} else if l2=l1 then{如果相等则进入详细分析} begin i:=l1; while (i>0)and(a[i]=b[i]) do dec(i);{从高到低依次检索AB每位的大小,如果有非等于则退出} if a[i]<1000 then write('0'); if c<100 then write('0'); if c<10 then write('0'); write(c); end; 程序源代码: {PASCAL} Program a1; var a,b,c:array [1..100] of integer; x2,l1,l2,i:integer; p:boolean; s:string; begin readln(s); l1:=pos('-',s); for i:=1 to l1-1 do a[l1-i]:=ord(s[i])-48; dec(l1); x2:=length(s); l2:=x2-l1-2; for i:=l1+2 to x2 do b[x2-i]:=ord(s[i])-48; if l2>l1 then p:=true else if l2=l1 then begin i:=l1; while (i>0)and(a[i]=b[i]) do dec(i); if a[i]<0 then begin c[i]:=c[i]+10; dec(c[i+1]); end; i:=l2; while c[i]=0 do dec(i); write('-'); for l2:=i downto 1 do write(c[i]); writeln; end else begin for i:=1 to l1 do c[i]:=a[i]-b[i]; for i:=1 to l1 do if c[i]<0 then begin c[i]:=c[i]+10; dec(c[i+1]); end; i:=l1; while c[i]=0 do dec(i); for l1:=i downto 1 do write(c[i]); writeln; end; end. {水平不足之处请见谅} #include #include #include using namespace std; char a[1000]={0},b[1000]={0},d[1000],c[1000]={0};int l1,l2,k,i; int main() { ifstream cin("1.txt",ios::in); cin.getline(c,1000); cin.getline(d,1000); l1=strlen(c);l2=strlen(d); for(i=0;il2){k=l1;}else{k=l2;} for(i=0;i=0;i--) { a[i]+='0'; cout<<
望采纳哦~
刘欣然在2020-04-04 22:04:50追加了内容
高级光能
高精度加法
题目描述:
给出两个整数(a、b),计算它们的和。
输入:一行两个整数(1 < a,b < 10^1000)
输出:一行一个整数,表示a+b的和
这是一道经典的高精度加法,首先注意两个整数上限都是1000位,普通的int肯定爆上限(long long也会爆,不用想),所以只能手写。。。
那具体怎么手写呢?
先来分析一下,普通算加法时必须需要列竖式对吧,这种竖式就可以通过编程模拟出来。很简单就能看出,首先我们将两个数的每一位都相加,例如333和666的每一位都相加,得到999。
当然很容易看出,这样做是肯定不够的,我们要处理每一位进位的情况,也就是检测每一位,超过十上一位加一,但这里要处理一个bug。
举个栗子500和500
这里相加得出的结果是1000。。。
那如果我们把500当成数组存且500中的5存在a[0]的话,就只能把1000里的1存在a[-1]了。
等等
a[-1] ?!
好吧,为了避免这种bug,我这里推荐在存的时候倒过来存
也就是说500要这样存:
a[0] a[1] a[2]
0 0 5
然后每次进位就可以存到a[i+1]了,同时答案的长度如果要记录下来的话,这里得加1。当然推荐把加法写成函数。
下面请看我写的实例:
#include <iostream>
#include <cstring>
using namespace std;
#define MAXLEN 1005
string la, lb; // 用字符串输入两个数
int a[MAXLEN], b[MAXLEN], ans[MAXLEN]; // a是第一个数,b是第二个数, ans是和
int len; // 和的长度
void ADD() // 加法函数
{
for (int i = 0; i < len; i++)
{
ans[i] += (a[i] + b[i]); // 每一位相加
if (ans[i] >= 10) // 处理进位
{
ans[i+1]++;
ans[i] -= 10;
}
}
if (ans[len] >= 1) len++; // 如果有最高位进位,长度+1
}
int main()
{
cin >> la >> lb; // 输入
memset(ans, 0, MAXLEN); // 将ans的每一位初始化为零
for (int i = 0; i < la.length(); i++) a[la.length()-i-1] = la[i] - '0'; // 倒着输入第一个数
for (int i = 0; i < lb.length(); i++) b[lb.length()-i-1] = lb[i] - '0'; // 倒着输入第二个数
len = max(la.length(), lb.length()); // 将答案的长度暂定为第一个和第二个数的长度中最长的一个
ADD(); // 加法
for (int i = len-1; i >= 0; i--) cout << ans[i]; // 输出
return 0;
}
高精度减法
高精度减法和高精度加法相比,减法在差为负数时处理的细节更多一点。
中文名
高精度减法
相 比
细 节
判断被减数与减数的大小
算法流程
读入被减数S1,S2
目
录
- 1基本内容
1基本内容
高精度减法 1、和高精度加法相比,减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;在程序实现上用一个变量来存储符号位,用另一个数组存差的绝对值。 2、算法流程: (1)读入被减数S1,S2(字符串); (2)置符号位:判断被减数是否大于减数:大则将符号位置为空;小则将符号位置为“-”,交换减数与被减数; (3)被减数与减数处理成数值,放在数组中; (4)运算: A、取数; B、判断是否需要借位; C、减,将运算结果放到差数组相应位中; D、判断是否运算完成:是,转5;不是,转A; (5)打印结果:符号位,第1位,循环处理第2到最后一位; 3、细节: ▲如何判断被减数与减数的大小:字符串知识 ①(1)首先将两个字符串的位数补成一样(因为字符串的比较是从左边对齐的;两个字符串一样长才能真正地比较出大小):短的在左边补0 k1:=length(s1); k2:=length(s2); if k1>k2 then for i:=1 to k1-k2 do s2:='0'+s2 else for i:=1 to k2-k1 do s1:='0'+s1; (2)接着比较大小:直接比较字符串大小 fh:=''; if s1l1 then p:=true{开始分析数值AB的大小,如果B位数高则B更大} else if l2=l1 then{如果相等则进入详细分析} begin i:=l1; while (i>0)and(a[i]=b[i]) do dec(i);{从高到低依次检索AB每位的大小,如果有非等于则退出} if a[i]<1000 then write('0'); if c<100 then write('0'); if c<10 then write('0'); write(c); end; 程序源代码: {PASCAL} Program a1; var a,b,c:array [1..100] of integer; x2,l1,l2,i:integer; p:boolean; s:string; begin readln(s); l1:=pos('-',s); for i:=1 to l1-1 do a[l1-i]:=ord(s[i])-48; dec(l1); x2:=length(s); l2:=x2-l1-2; for i:=l1+2 to x2 do b[x2-i]:=ord(s[i])-48; if l2>l1 then p:=true else if l2=l1 then begin i:=l1; while (i>0)and(a[i]=b[i]) do dec(i); if a[i]<0 then begin c[i]:=c[i]+10; dec(c[i+1]); end; i:=l2; while c[i]=0 do dec(i); write('-'); for l2:=i downto 1 do write(c[i]); writeln; end else begin for i:=1 to l1 do c[i]:=a[i]-b[i]; for i:=1 to l1 do if c[i]<0 then begin c[i]:=c[i]+10; dec(c[i+1]); end; i:=l1; while c[i]=0 do dec(i); for l1:=i downto 1 do write(c[i]); writeln; end; end. {水平不足之处请见谅} #include #include #include using namespace std; char a[1000]={0},b[1000]={0},d[1000],c[1000]={0};int l1,l2,k,i; int main() { ifstream cin("1.txt",ios::in); cin.getline(c,1000); cin.getline(d,1000); l1=strlen(c);l2=strlen(d); for(i=0;il2){k=l1;}else{k=l2;} for(i=0;i=0;i--) { a[i]+='0'; cout<<
高级光能
大体思路其实是把每个数放到数组里,用空间换时间
C++和C中经常有大数运算,
大数就是,这个long long型都存不下的数嘛。那么怎么对他们进行运算呢。
思想如下:
我们一定要用一个什么来存这个大数的各个位。模拟竖式加减法。从最低位开始,因此我们要将这个存放大数位数的东西倒置过来。
大数加法
比如 1234567+789
就可以写成如下形式
7 6 5 4 3 2 1
9 8 7
7+9=16
6存入新的容器里面去。向下进一个1,依次类推。
大抵模拟就是这样。
我之前是用数组慢慢存放。字符数组转化成整数数组。模拟再加减。这样很好实现,只不过,代码太过于冗杂。今天也是在师父的指导下,开始用string这个类,来写这个大数加减。
虽然先开始我觉得这样写很赖皮,不过实在是,比我之前用的方法简单多了。所以不好意思贴我之前用数组写的代码了。很low.
主要代码如下:
既然说倒置了。。前面可以用reverse() 加法当然首先reverse就好。
//模仿竖式加法。从低位加起,所以倒置
; //先将a[i]变成数字
//再将b[i]变成数字
//相加再变成字符
//判断相加是否大于10
carry的作用是表示是否进位。carry是int型,所以要在字符和数字间做交换。
最后还要记得做一个判断。
如果最高位上的还要+1,那么这个sum后面当然也要添一个’1’啦。
加法的思想就是这样。。减法有点难想,毕竟我粗心,而且对string用的不熟,以至于十二点才把题给过了。
大数减法
减法也是同样模拟竖式运算。
123456-789
6 5 4 3 2 1
9 8 7 -
6-9=-3。这里不同的就是,要把-3+10=7,存入sum里面才行。
减法的判断有点多,首先判断两个字符串的长度
至于carry为什么要先加a[i]再-b[i]。这个也是模拟的减法运算。 要注意的就是,carry是一个表示是否向前借位的值。之前这里不是很明白,所以出了很多错。carry会有两种值,-1和0。同样也要在字符和整数中做交换。
还有一个地方困惑了很久的就是,我要怎么保证b读完的时候,a还能继续读。之前i
int ind=-1;
while(sum[++ind]=='0');
if(ind!=-1)
sum=sum.substr(ind);
资深天翼
输入两个数到两个变量中,然后用赋值语句求他们的和,输出。
但是,我们知道,在C++中任何数据类型都有一定表示范围。当两个被加数很大时,上述算法显然不能求出精确解,因此寻求另外一种方法。
在读小学时,我们做加法都采用竖式方法,这样,我们可以写出两个整数相加的算法。
我们用数组a、b分别存储加数和被加数,用数组c存储结果。则上例有a[3]=8,a[2]=5,a[1]=6;b[3]=2,b[2]=5,b[1]=5;c[4]=1,c[3]=1,b[2]=1,b[1]=1。两数相加如图所示。
因此,算法描述如下。
/*a、b、c均为数组,存储被加数、加数、结果*/
int c[100];
void add(int a[],int b[])
{
int i=1,x=0;//x为进位
while( (i<=a数组长度) || (i<=b数组长度) )
{
c[i]=a[i]+b[i]+x;//第i位相加并加上次的进位
x=c[i]/10;//向高位进位
c[i]%=10;//存储第i位的值
i++;//位置下标
}
}
————————————————
版权声明:本文为CSDN博主「Alex_McAvoy」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011815404/java/article/details/79920270