问题标题: 酷町堂:高精度加减法思路!!!

1
0

0
已采纳
刘欣然
刘欣然
高级光能
高级光能

高精度加法

题目描述:
给出两个整数(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、和高精度加法相比,减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;在程序实现上用一个变量来存储符号位,用另一个数组存差的绝对值。   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追加了内容

0
邹昊轩
邹昊轩
资深光能
资深光能

我以前没经过几次高精度,我可以告诉你:高精度要用函数。

0
赵逸凡
赵逸凡
初级启示者
初级启示者

如果你没学到就不要问,如果你学到了你去问老师吧。

0
王俊杰
王俊杰
高级光能
高级光能

高精度加法

题目描述:
给出两个整数(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、和高精度加法相比,减法在差为负数时处理的细节更多一点:当被减数小于减数时,差为负数,差的绝对值是减数减去被减数;在程序实现上用一个变量来存储符号位,用另一个数组存差的绝对值。   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<<

0
缪鲲鹏
缪鲲鹏
新手光能
新手光能

这个学了就会, 没学就别去想

0
李致远
李致远
高级光能
高级光能

大体思路其实是把每个数放到数组里,用空间换时间

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);
 

0
陈曦
陈曦
资深天翼
资深天翼

输入两个数到两个变量中,然后用赋值语句求他们的和,输出。

但是,我们知道,在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

0
李瑞曦
李瑞曦
高级天翼
高级天翼

高精度这种题,最好让大佬来解决!

0
我要回答