大數的四則運算(加法、減法、乘法、除法)

大數的四則運算(加法、減法、乘法、除法)

前言:

? ? 在計算機中數字表示的范圍是有限制的,比如我們熟知的 int、float、double 等數據類型所能表示的范圍都是有限的,如果我們要對位數達到幾十位、幾百位、上千位的大整數進行計算,這些數據類型顯然不能滿足我們的要求,因此我們需要通過算法來實現這些功能。

?

1、大數加法

? ? 兩個大數我們可以用數組來保存,然后在數組中逐位進行相加,再判斷該位相加后是否需要進位,為了方便計算,我們將數字的低位放在數組的前面,高位放在后面。

下面是兩個正的大整數相加算法的C語言參考代碼:

復制代碼
 1 #include<stdio.h>2 #include<string.h>3 4 #define MAX 1000    // 大數的最大位數?5 6  7 /*8   大數加法 9   參數: 
10   num1為第一個大數,用字符數組保存
11   num2為第二個大數
12   sum數組保存相加的結果  即:num1+num2=sum
13   返回值:返回數組sum的有效長度,即計算結果的位數 
14  */
15 int Addition(char num1[], char num2[], int sum[])
16 {
17     int i, j, len;
18     int n2[MAX] = {0};
19     int len1 = strlen (num1); // 計算數組num1的長度,即大數的位數 
20     int len2 = strlen (num2); // 計算數組num2的長度,即大數的位數 
21 
22     len = len1>len2 ? len1 : len2; // 獲取較大的位數
23     //將num1字符數組的數字字符轉換為整型數字,且逆向保存在整型數組sum中,即低位在前,高位在后
24     for (i = len1-1, j = 0; i >= 0; i--, j++) 
25         sum[j] = num1[i] - '0';
26     // 轉換第二個數 
27     for (i = len2-1, j = 0; i >= 0; i--, j++)
28         n2[j] = num2[i] - '0';
29     // 將兩個大數相加 
30     for (i = 0; i <= len; i++)
31     {
32         sum[i] += n2[i];  // 兩個數從低位開始相加 
33         if (sum[i] > 9)   // 判斷是否有進位 
34         {   // 進位 
35             sum[i] -= 10;
36             sum[i+1]++;
37         }
38     }
39     if(sum[len] != 0)  // 判斷最高位是否有進位 
40         len++;
41     return len;   // 返回和的位數 
42 }
43 
44 int main()
45 {
46     int i, len;
47     int sum[MAX] = {0}; // 存放計算的結果,低位在前,高位在后,即sum[0]是低位 
48     char num1[] = "1234567891234567891234"; // 第一個大數 
49     char num2[] = "2345678912345678913345"; // 第二個大數 
50     len = Addition(num1, num2, sum);    // 兩數相加 
51     printf("%s\n  +\n%s\n  =\n", num1, num2);
52     // 反向輸出求和結果
53     for (i = len-1; i >= 0; i--)
54         printf("%d", sum[i]);
55     printf("\n"); 
56     return 0;
57 }
復制代碼

?

2、大數減法

? ? 相減算法也是從低位開始減的。先要判斷被減數和減數哪一個位數長,若被減數位數長是正常的減法;若減數位數長,則用被減數減去減數,最后還要加上負號;當兩數位數長度相等時,最好比較哪一個數字大,否則負號處理會很繁瑣;處理每一項時要,如果前一位相減有借位,就先減去上一位的借位,無則不減,再去判斷是否能夠減開被減數,如果減不開,就要借位后再去減,同時置借位為1,否則置借位為0。

下面是C語言參考代碼:

復制代碼
  1 #include<stdio.h>2 #include<string.h>3 4 #define MAX 1000    // 大數的最大位數?5 6  7 /*8   大數減法 9   參數: 10   num1為被減數,用字符數組保存11   num2為減數 12   sum數組保存相減的結果   即:num1-num2=sum13   返回值:返回數組sum的有效長度,即計算結果的位數 14  */15 int Subtraction(char num1[], char num2[], int sum[])16 {17     int i, j, len, blag;18     char *temp;19     int n2[MAX] = {0};20     int len1 = strlen(num1); // 計算數組num1的長度,即大數的位數 21     int len2 = strlen(num2); // 計算數組num2的長度,即大數的位數22     23     // 在進行減法之前要進行一些預處理 24     blag = 0; // 為0表示結果是正整數,為1表示結果是負整數 25     if(len1 < len2) // 如果被減數位數小于減數26     {27         blag = 1; // 標記結果為負數28         // 交換兩個數,便于計算 29         temp = num1;30         num1 = num2;31         num2 = temp;32         len = len1;33         len1 = len2;34         len2 = len;35     }36     else if(len1 ==len2) // 如果被減數的位數等于減數的位數37     {  38         // 判斷哪個數大 39         for(i = 0; i < len1; i++)40         {41             if(num1[i] == num2[i])42                 continue;43             if(num1[i] > num2[i])44             {45                 blag = 0; // 標記結果為正數 46                 break;47             } 48             else49             {50                 blag = 1; // 標記結果為負數 51                 // 交換兩個數,便于計算 52                 temp = num1;53                 num1 = num2;54                 num2 = temp;55                 break;56             } 57         } 58     }59     len = len1>len2 ? len1 : len2; // 獲取較大的位數60     //將num1字符數組的數字轉換為整型數且逆向保存在整型數組sum中,即低位在前,高位在后61     for (i = len1-1, j = 0; i >= 0; i--, j++) 62         sum[j] = num1[i] - '0';63     // 轉換第二個數 64     for (i = len2-1, j = 0; i >= 0; i--, j++)65         n2[j] = num2[i] - '0';66     // 將兩個大數相減 67     for (i = 0; i <= len; i++)68     {69         sum[i] = sum[i] - n2[i]; // 兩個數從低位開始相減 70         if (sum[i] < 0)   // 判斷是否有借位 71         {    // 借位 72             sum[i] += 10;73             sum[i+1]--;74         }75     }76     // 計算結果長度 77     for (i = len1-1; i>=0 && sum[i] == 0; i--)78         ;79     len = i+1;80     if(blag==1)81     {82         sum[len] = -1;  // 在高位添加一個-1表示負數 83         len++;84     }85     return len;   // 返回結果的位數 86 }87 88 int main()89 {90     int i, len;91     int sum[MAX] = {0}; // 存放計算的結果,低位在前,高位在后,即sum[0]是低位 92     char num1[] = "987654321987654321"; // 第一個大數 93     char num2[] = "123456789123456789"; // 第二個大數 94     len = Subtraction(num1, num2, sum);    // 兩數相減 95     // 輸出結果96     printf("%s\n  -\n%s\n  =\n", num1, num2);97     if(sum[i=len-1] < 0) // 根據高位是否是-1判斷是否是負數98     {99         printf("-"); // 輸出負號
100         i--;
101     }
102     for (; i >= 0; i--)
103         printf("%d", sum[i]);
104     printf("\n"); 
105     return 0;
106 } 
復制代碼

?

3、大數乘法

? ? 首先說一下乘法計算的算法,從低位向高位乘,在豎式計算中,我們是將乘數第一位與被乘數的每一位相乘,記錄結果,之后,用第二位相乘,記錄結果并且左移一位,以此類推,直到計算完最后一位,再將各項結果相加,得出最后結果。

? ? 計算的過程基本上和小學生列豎式做乘法相同。為了編程方便,并不急于處理進位,而是將進位問題留待最后統一處理。

? ? 總結一個規律: 即一個數的第i 位和另一個數的第j 位相乘所得的數,一定是要累加到結果的第i+j 位上。這里i, j 都是從右往左,從0 開始數。
? ? ans[i+j] = a[i]*b[j];

? ? 另外注意進位時要處理,當前的值加上進位的值再看本位數字是否又有進位;前導清零。

下面是C語言的兩個正大數相乘的參考代碼:

復制代碼
 1 #include<stdio.h>2 #include<string.h>3 4 #define MAX 1000    // 大數的最大位數?5 6  7 /*8   大數乘法 9   參數: 
10   num1為第一個因數,用字符數組保存
11   num2為第二個因數
12   sum數組保存相乘的結果  即:num1*num2=sum
13   返回值:返回數組sum的有效長度,即計算結果的位數 
14  */
15 int Multiplication(char num1[],char num2[], int sum[])
16 {
17     int i, j, len, len1, len2;
18     int a[MAX+10] = {0};
19     int b[MAX+10] = {0};
20     int c[MAX*2+10] = {0};
21     
22     len1 = strlen(num1);
23     for(j = 0, i = len1-1; i >= 0; i--) //把數字字符轉換為整型數 
24         a[j++] = num1[i]-'0';
25     len2 = strlen(num2);
26     for(j = 0, i = len2-1; i >= 0; i--)
27         b[j++] = num2[i]-'0';
28     
29     for(i = 0; i < len2; i++)//用第二個數乘以第一個數,每次一位 
30     {
31         for(j = 0; j < len1; j++)
32         {
33             c[i+j] += b[i] * a[j]; //先乘起來,后面統一進位
34         }
35     }
36     
37     for(i=0; i<MAX*2; i++) //循環統一處理進位問題
38     {
39         if(c[i]>=10)
40         {
41             c[i+1]+=c[i]/10;
42             c[i]%=10;
43         }
44     }
45 
46     for(i = MAX*2; c[i]==0 && i>=0; i--); //跳過高位的0
47     len = i+1; // 記錄結果的長度 
48     for(; i>=0; i--)
49         sum[i]=c[i];
50     return len; 
51 }
52 
53 int main()
54 {
55     int i, len;
56     int sum[MAX*2+10] = {0}; // 存放計算的結果,低位在前,高位在后,即sum[0]是低位 
57     char num1[] = "123456789123456789"; // 第一個大數 
58     char num2[] = "123456789123456789"; // 第二個大數 
59     len = Multiplication(num1, num2, sum);
60     // 輸出結果
61     printf("%s\n  *\n%s\n  =\n", num1, num2);
62     for(i = len-1; i>=0; i--)
63         printf("%d", sum[i]); 
64     printf("\n"); 
65     return 0;
66 } 
復制代碼

?

4、大數除法

? ? 大數除法是四則運算里面最難的一種。不同于一般的模擬,除法操作不是模仿手工除法,而是利用減法操作來實現的。其基本思想是反復做除法,看從被除數里面最多能減去多少個除數,商就是多少。逐個減顯然太慢,要判斷一次最多能減少多少個整數(除數)的10的n次方。

以7546除以23為例:

? ? 先用7546減去23的100倍,即減去2300,可以減3次,余下646,此時商就是300 (300=100*3);

? ? 然后646減去23的10倍,即減去230,可以減2次,余下186,此時商就是320 (320=300+10*2);

? ? 然后186減去23,可以減8次,余下2,此時商就是328 (328=320+1*8);

? ? 因為2除以23的結果小于1,而我們又不用計算小數點位,所以不必再繼續算下去了。

下面是C語言的兩個正大數相除的參考代碼,計算結果中沒有小數:

復制代碼
  1 #include<stdio.h>2 #include<string.h> 3 #define MAX 1000    // 大數的最大位數?4 5 // 注: 6 // 本代碼在以下博客代碼中進行修改: 7 // http://www.cnblogs.com/javawebsoa/archive/2013/08/01/3231078.html8 // 9 10 11 /*12   函數SubStract功能:13   用長度為len1的大整數p1減去長度為len2的大整數p214   結果存在p1中,返回值代表結果的長度15   不夠減:返回-1 , 正好夠:返回016 */ 17 int SubStract(int *p1, int len1, int *p2, int len2)18 {19     int i;20     if(len1 < len2)21         return -1;22     if(len1 == len2 )23     {                        // 判斷p1 > p224         for(i = len1-1; i >= 0; i--)25         {26             if(p1[i] > p2[i])   // 若大,則滿足條件,可做減法27                 break;28             else if(p1[i] < p2[i]) // 否則返回-129                 return -1;30         }31     }32     for(i = 0; i <= len1-1; i++)  // 從低位開始做減法33     {34         p1[i] -= p2[i];         // 相減 35         if(p1[i] < 0)           // 若是否需要借位36         {   // 借位 37             p1[i] += 10;38             p1[i+1]--;39         }40     }41     for(i = len1-1; i >= 0; i--)  // 查找結果的最高位42     {43         if( p1[i] )             //最高位第一個不為044             return (i+1);       //得到位數并返回45     } 46     return 0;                   //兩數相等的時候返回047 }48 49 50 /*51   大數除法---結果不包括小數點 52   num1 被除數53   num2 除數 54   sum  商,存放計算的結果,即:num1/num2=sum55   返回數組sum的有效長度,即商的位數 56 */ 57 int Division(char num1[], char num2[], char sum[])58 {59     int k, i, j;60     int len1, len2, len=0;     //大數位數61     int dValue;                //兩大數相差位數62     int nTemp;                 //Subtract函數返回值63     int num_a[MAX] = {0};      //被除數64     int num_b[MAX] = {0};      //除數65     int num_c[MAX] = {0};      //商 66 67     len1 = strlen(num1);       //獲得大數的位數68     len2 = strlen(num2);69     70     //將數字字符轉換成整型數,且翻轉保存在整型數組中 71     for( j = 0, i = len1-1; i >= 0; j++, i-- )72         num_a[j] = num1[i] - '0';73     for( j = 0, i = len2-1; i >= 0; j++, i-- )74         num_b[j] = num2[i] - '0';75 76     if( len1 < len2 )          //如果被除數小于除數,直接返回-1,表示結果為077     {78         return -1;79     }80     dValue = len1 - len2;      //相差位數81     for (i = len1-1; i >= 0; i--)    //將除數擴大,使得除數和被除數位數相等82     {83         if (i >= dValue)84             num_b[i] = num_b[i-dValue];85         else                         //低位置086             num_b[i] = 0;87     }88     len2 = len1;89     for(j = 0; j <= dValue; j++ )    //重復調用,同時記錄減成功的次數,即為商90     {91         while((nTemp = SubStract(num_a, len1, num_b+j, len2-j)) >= 0)92         {93             len1 = nTemp;            //結果長度94             num_c[dValue-j]++;       //每成功減一次,將商的相應位加195         }96     }97     // 計算商的位數,并將商放在sum字符數組中 98     for(i = MAX-1; num_c[i] == 0 && i >= 0; i-- );  //跳過高位0,獲取商的位數 99     if(i >= 0)
100         len = i + 1; // 保存位數 
101     for(j = 0; i >= 0; i--, j++)     // 將結果復制到sum數組中 
102         sum[j] = num_c[i] + '0';
103     sum[j] = '\0';   // sum字符數組結尾置0 
104     return len;      // 返回商的位數 
105 } 
106 
107 
108 int main()
109 {
110     int i;
111     int len;                // 商的位數
112     char num1[MAX] = "1234567899876543210";   // 第一個大數
113     char num2[MAX] = "20160415123025";              // 第二個大數
114     char sum[MAX] = {0};    // 計算結果 
115 
116     //scanf("%s", num1);      //以字符串形式讀入大數
117     //scanf("%s", num2);
118     
119     len = Division(num1, num2, sum); 
120     
121     //輸出結果
122     printf("%s\n  ÷\n%s\n  =\n", num1, num2);
123     if( len>=0 )
124     {
125         for(i = 0; i < len; i++ )
126             printf("%c", sum[i]);
127     }
128     else
129     {
130         printf("0");
131     }
132     printf("\n");
133     
134     return 0;
135 }
復制代碼

?

5、使用Java提供的類

? ? 在Java中提供了BigInteger類和BigDecimal類,分別用來處理大整數和大浮點數,我們只要調用里面提供的方法就能很方便的進行大數的四則運算,具體實現可參考:

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/445396.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/445396.shtml
英文地址,請注明出處:http://en.pswp.cn/news/445396.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數組基操三連(1)

題目&#xff1a; 給定一個數組arr&#xff0c;求出需要排序的最短子數組長度 要求&#xff1a; 時間o(n),空間o(1) 思路&#xff1a; 有序的數組中&#xff0c;任意一個數字&#xff0c;一定小于左邊的數大于右邊的數。 我們找到的需要排序的子數組&#xff0c;顯然是比右邊…

IT互聯網公司的筆試的輸入輸出- c++ python

文章目錄目錄c方式1&#xff1a;方式2&#xff1a;Python方式1&#xff1a;方式2&#xff1a;方式3&#xff1a;目錄 c 方式1&#xff1a; 第一種情況&#xff1a;輸入n個數&#xff0c;存放在數組中 #include <iostream> #include <vector> using namespace st…

隨機過程1

隨機過程1概述1.參考書目2.主要內容3.概率論--基本概念回顧3.1對“不確定性”的認識3.2 應對“不確定性”應該怎么做3.3隨機變量&#xff08;Random Variable&#xff09;3.4分布函數&#xff08;Distribution Function&#xff09;3.5概率密度&#xff08;Density&#xff09;…

數組基操三連(4)

題目一 給定一個長度為N的整型數組arr&#xff0c;其中有N個互不相等的自然數1~N 請實現arr的排序 但是不要把下標0~N-1位置上的數值通過直接賦值的方式替換成1~N。 要求&#xff1a;時間復雜度為O(N)&#xff0c;額外空間復雜度為O(1)。 思路&#xff1a;從左向右檢查&…

Linux(1)-touch,mkdir,rm,mv,cp,ls,cd,cat

Linux1-實用終端命令1. touch, mkdir2. rm, mv, cp3. ls(通配符),cd(絕對/相對路徑)4. cat, more/less文件內容瀏覽文件/目錄-增刪查改, 文件內容查看.1. touch, mkdir touch新文件 &#xff1a;在當前文件夾下&#xff0c;創建文件。文件不存在則創建新文件&#xff1b;文件存…

java常用類介紹及源碼閱讀(ArrayList)

java.util 類 ArrayList<E> 繼承關系&#xff1a; java.lang.Objectjava.util.AbstractCollection<E>java.util.AbstractList<E>java.util.ArrayList<E>List 接口的動態數組的實現。 實現了所有可選列表操作&#xff0c;并允許包括 null 在內的所有…

tests1

ls,cd,tardone

數組精選題目三連(5)

子數組的最大累加和問題 輸入一個整形數組&#xff0c;求數組中連續的子數組使其和最大。比如&#xff0c;數組x 應該返回 x[2..6]的和187. 這四個代碼完成的功能都是求最大子數組&#xff08;注意用詞準確&#xff0c;子數組連續&#xff0c;子序列可以不連續&#xff09;。…

大數據學習(1)-大數據概述

文章目錄目錄大數據產生背景大數據概念大數據影響大數據應用大數據關鍵技術大數據產業大數據&#xff0c;云計算&#xff0c;物聯網關系云計算物聯網大數據&#xff0c;物聯網&#xff0c;云計算三者之間聯系目錄 大數據產生背景 三次信息化浪潮 根據IBM前首席執行官郭士納福…

java常用類介紹及源碼閱讀(LinkedList)

java.util 類 LinkedList<E> java.lang.Objectjava.util.AbstractCollection<E>java.util.AbstractList<E>java.util.AbstractSequentialList<E>java.util.LinkedList<E> List 接口的鏈接列表實現。實現所有可選的列表操作&#xff0c;并且允…

矩陣論-集合與映射,線性空間及其性質

線性空間與線性變換綜述1.1 線性空間1.1.1 集合與映射1.1.2 線性空間及其性質綜述 本系列博文主要總結學習矩陣論的心得筆記&#xff0c;參考數目《矩陣論》–張凱院&#xff1b;整個文章的整理體系參照行書過程。 1.1 線性空間 1.1.1 集合與映射 1.集合&#xff1a;將很多…

機器學習知識總結系列-機器學習中的數學-概率與數理統計(1-3-1)

文章目錄目錄1.概率與統計1.1 機器學習與概率統計之間的關系1.2 重要的統計量1.2.1 期望1.2.2 方差1.2.3 協方差&#xff0c;相關系數協方差相關系數1.2.4 矩1.3 重要的定理與不等式1.4 用樣本估計參數目錄 1.概率與統計 1.1 機器學習與概率統計之間的關系 1.什么是概率問題…

redis——事件

redis服務器是一個事件驅動程序。 需要處理兩類事件&#xff1a; 1&#xff09;文件事件&#xff1a;redis是通過套接字與客戶端或者其他服務器連接的&#xff0c;而文件事件就是服務器對套接字操作的抽象。 2&#xff09;時間事件&#xff1a;服務器對一些定時操作的抽象。…

自然語言處理(1)-概述

自然語言處理-概述概述1.基本概念2.人類語言技術HLT發展簡史3.HLT 研究內容4.基本問題和主要困難5.基本研究方法概述 本系列文章計劃總結整理中國科學院大學宗成慶老師《自然語言處理》課程相關知識&#xff0c;參考數目《統計自然語言處理》-第二版&#xff0c;宗成慶。 1.基…

redis——客戶端

redis服務器是典型的一對多服務器&#xff0c;通過使用由IO多路復用技術實現的文件事件處理器&#xff0c;redis服務器使用了單線程單進程的方式來處理請求。 客戶端的屬性 描述符 客戶端狀態的 fd 屬性記錄了客戶端正在使用的套接字描述符&#xff1a; typedef struct red…