【模板+詳解】 高精度加法


嗯...

 

首先讓我們引入高精度這個東西....

 

相信大家都會做A+B Problem 這道題....輸出的是A+B 的值....

 

可你想過沒有,如果A= 5983461827658923256597314923593449492545242655621498167329758256231975822594359252779832914372582828292235591346798922923,

B = 9382872892382859234389628259232359438768953797679368296159683689865328523725925829753298653219197389235498228659659373291973652564256594,

 

而這時,所有的類型都無法存儲A和B這兩個數....而這時,高精度就要出馬了...(附圖關於數據類型范圍....

 

 

這里首先講的是高精度的加法。下面是一個偽代碼,主要表達了高精度加法的主要流程:

1 read();//讀入兩個大整數;
2 calsum();//求和;
3 print();//輸出結果;
偽代碼—流程

 

Question 1 :

這么大的數,如何進行讀入?

 

Answer   1:

當輸入的數很大時,可采用字符串方式接收。輸入要符合整數的輸入規則:連續輸入每位數字,中間無空格。

 

在這里會牽扯到另一部分的知識——字符串...其實字符串還是比較常用的...

下面就簡單提幾方面:

 

Part 1:

字符串定義方式:

string s; // 直接定義
char s[1007];//用一個字符數組模擬字符串,這種的靈活性與速度上有優勢

不同方式定義的字符串,對應的函數也不同
如  string s;   len = s.length();
而  char s[1007]; len = strlen(s);

 

Part  2:

字符串的讀入:

這里主要介紹三種方式:1. cin    2.scanf    3.gets

 

下面給大家演示一下它們的具體的讀入方法:

1.cin:

1         string s1,s2;
2     cin>>s1>>s2;
3     int lena = s1.length();
4     int lenb = s2.length();
5     
6     cout<<s1<<" "<<s2<<endl;
7     cout<<lena<<" "<<lenb;
cin讀入

 

2.scanf://輸入的兩個字符串:可以在同一行,中間以空格隔開。也可以各占一行。

 1 char s1[1010],s2[1010];
 2 int main()
 3 {
 4     scanf("%s%s",s1,s2); // scanf("%s%s",&s1,&s2);&可省略
 5     int lena=strlen(s1); //strlen()函數需要頭文件cstring
 6     int lenb=strlen(s2);
 7     
 8     cout<<s1<<" "<<s2<<endl;
 9     cout<<lena<<" "<<lenb;
10 } 
scanf讀入

 

3.gets://輸入的兩個字符串必須各占一行

1 char s1[1010],s2[1010];
2 gets(s1);
3 gets(s2);
4 lena=strlen(s1);
5 lenb=strlen(s2);
gets讀入

 

注意:

scanf、cin遇空格或回車符則認為當前字符串結束
gets遇回車符則認為當前字符串結束

 

Question  2:

我們將讀入的數作為字符串接收了進來,可是怎么進行加減乘除等數學運算呢?

Answer   2:

拆成一位一位的數字,把它們存在一個數組中,一個數組元素表示一位數字……解釋:“拆”

 

例如:

 

 詳細過程:——字符串讀入,數組保存(見代碼

1 //利用字符串函數和操作運算,將每一位數取出,存入數組中。
2 
3 //假設已經利用字符串s讀取數據 
4     lena=s.length();          //用lena存放字符串s的位數 
5         for(i=1;i<=lena;i++)
6         a[i]=s[lena-i] -'0';  //將數串s轉換為數組a,注意:倒序存儲
7     
保存

 

 

解釋倒序保存的原因:

在平常,數字從左到右依次為從高位到低位....可這里卻與日常的習慣相反。因為在存儲時我們首先能確定的就是最低位,所以設它為第一位,而高位無法確定,因為在存儲之前求出字符串的長度比較麻煩,所以我們用下標較大的數組存儲高位,因為它的最高位無法確定....

 

 

Question  3:

兩個高精度數已經分別保存在數組a和b中,下一步,應該如何求和?

Answer   3:

用到了小學所學的”豎式計算“的思想:

運算的次數為:max(lena, lenb);

 

程序實現:

 

方法一:

模擬手工計算,設置一個進位變量m,但是此方式比較麻煩:

 1 for (int i=1;i<=lena;i++) 
 2     a[i]=s1[lena-i]-48;//由字符轉向真正意義的數字 ,並且為倒序 
 3 for (int i=1;i<=lenb;i++) 
 4     b[i]=s2[lenb-i]-48;//同上 
 5 lenc = max(lena, lenb);
 6 for (int i=1;i<=lenc;i++)
 7 {
 8     c[i]=(m+a[i]+b[i])%10;
 9     m=(m+a[i]+b[i])/10;//進位 
10 }
11 if (m) {//判斷最高位是否需要進位 
12     lenc++;
13     c[lenc]=1;
14 } 
方法一

 

方法二:

先計算,最后處理進位,比方法一要簡單:

1 for (int i=1;i<=lenc;i++)
2     c[i]=a[i]+b[i];//先計算 
3 for (int i=1;i<=lenc;i++)
4 {
5     c[i+1]=c[i+1]+c[i]/10;
6     c[i]=c[i]%10;//后處理進位 
7 }
8 if (c[lenc+1]) lenc++;//判斷最高位是否需進位 
方法二

 

方法三:

方法二的改進,去掉c數組:

1 for (int i=1;i<=lena;i++)  
2     a[i]=a[i]+b[i]; //直接加在a數組中 
3 for (int i=1;i<=lena;i++)
4 {
5     a[i+1]=a[i+1]+a[i]/10;//進位 
6     a[i]=a[i]%10;//保留 
7 }
8 if (a[lena+1]) lena++;//特判 
方法三

 

最后的問題:

——運算結果的輸出:

1 for (i=lenc;i>=1;i--) 
2         printf("%d", c[i]);   //輸出結果
3 printf("\n");
4 
5 ==============================
6 
7 for (i=lenc;i>=1;i--) 
8         cout<<c[i];   //輸出結果
9 cout<<endl;
輸出

 

 

好的,關於高精度的每一個板塊已經說明清楚了,下面我們來看一下完整的高精度運算:

(模板============================================================

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 
 7 int a[506], b[506];
 8 int lena, lenb;
 9 int m;
10 string a1, b1;
11 
12 int main(){
13     cin>>a1>>b1;//定義的字符串讀入只可以用gets和cin,不能用scanf 
14     lena = a1.length();
15     lenb = b1.length();
16     for (int i = 0; i <= lena - 1; i++){
17         a[lena - i - 1] = a1[i] -'0';
18     }
19     for(int i = 0; i <= lenb - 1; i++){
20         b[lenb - i - 1] = b1[i] - '0';
21     }
22     if(lena >= lenb){
23         for(int i = 0; i <= lena - 1; i++){
24             int ss = a[i];
25             a[i] = (b[i] + a[i] + m)%10;
26             m = (ss + b[i] + m)/10;
27         }
28         if(m) a[lena] = m;
29         else lena--;
30         for(int i = lena; i >= 0; i--) printf("%d",a[i]);
31         return 0;
32     }
33     else{
34         for(int i = 0; i <= lenb-1; i++){
35             int ss = b[i];
36             b[i] = (b[i] + a[i] + m)%10;
37             m = (ss + a[i] + m) /10;
38         }
39         if(m) b[lenb] = m;
40         else lenb--;
41         for(int i = lenb; i >= 0; i--) printf("%d",b[i]);
42         return 0;
43     }
44     return 0;
45 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM