大数除法——超详细讲解
? ? ? ? 大數除法,本人認為是我目前見過大數算法中最難的一個(僅僅是個人想法),它與之前的大數加法乘法減法不同,有些難理解,下面我一點一點的分析,講解一下如何去實現大數除法。
? ? ?? 首先,我們要知道除法中,存在四個常用名稱,被除數,除數,商,余數(例如:53 / 8 = 6 余 5? ;其中53 為被除數,8為除數,6為商,5為余數 )當然我們可能會要求直接得到商,保留幾位小數(如:53 / 8 = 6.625)我們可以發現實際上小數部分0.625就是余數除以除數的結果(5 / 8 = 0.625 ),所以在之后的討論中,我們只討論如何得到商和余數。
? ? ? 一般我們在做除法問題時,也就是說數據類型之內的數之間的除法運算,我們一般會這樣去寫:
#include<stdio.h> int main() {long long n,m,mer,rem;scanf("%lld %lld",&n,&m);if(n<m) //被除數小于除數,商為0,余數為m{printf("商:0\n余數:%d\n",m);}if(n==m) //兩數相等,商為1,余數為0{printf("商:1\n余數:0\n");}if(n>m) //被除數大于除數{for(int i=1;;i++){n=n-1;if(n%m==0){mer=n/m;rem=i;break;}}printf("商:%lld\n余數:%lld\n",mer,rem);}return 0; }這是除法的一般方法,我們在計算的時候,首先要考慮,輸入的被除數是否比除數大,如果比除數小或者兩數相等,那么就可以直接得到商和余數了,這就不用在解釋了吧,如果被除數比除數大,那么我們就把被除數放循環里,每次減1,直到能與除數整除。這是常規做法,是有限制的,我們所遇到的數必須是long long類型以內的數,如果比long long 大,就沒辦法算了。怎么辦呢???
? ? 下面步入正題。。。。
? ? 由之前大數加法減法乘法中,我們可以知道,我們將大數以字符串的形式輸入,然后再轉化為數字,下面我截取了這部分代碼,我們可以看到,首先以字符串的形式輸入兩個大數,然后分別得出兩個大數的位數,最后再利用數組去倒序存儲字符串中的每一個元素,并轉化為數字,比如我之前舉例說明的 53 和 8 ,那么存到數組中就是 x[0]=3,x[1]=5;? y[0]=8;? 當然你也可以不倒置,直接順序讀入,但是在后面的計算過程中就會有一些變化,比如說得到的結果,倒置之后得到結果要去除前導0,不倒置得到的結果要去除后綴0。
while(~scanf("%s %s",a,b)){len1=strlen(a);//被除數位數len2=strlen(b);//除數位數for(i=len1-1,j=0;i>=0;i--)//將字符串中各個元素倒序儲存在數組中{x[j++]=a[i]-'0';//a[i]-'0'的意思是:a[i]是一個字符,如果為'1',那么在ASCLL是49,而'0'是48 ,所以 49 - 48 = 1,就轉化成了數字}for(i=len2-1,k=0;i>=0;i--){y[k++]=b[i]-'0';}? ?? 目前,我們要知道,在大數里我們已經不能再用剛才的常規方法去計算了,那怎么去計算呢?這就需要轉一下腦子了,將剛才的除法思想轉變為減法思想,舉個栗子:(一般我們計算7除以2等于3余1( 7 / 2 = 3 余 1)),現在變成減法思想( 7 / 2?→ 7 - 2 - 2 - 2 = 1 →減了3次,1比2小,不能再減了,即得到 7 / 2 = 3 余 1)怎么樣?腦子轉過來了嗎?如果還不行,你再用其他例子試試,理解了再往下看
? ? 現在我們就將除法變成減法了(開始上車了),再用 550 和 24 拿過來舉個栗子( 550-24-24-24-....-24 = 22)一共減了22次24,最后余22,你可能會說,這太暴力了吧,哈哈哈哈哈,當然不啊,下面請看下圖:
( 550 / 24 = 22 余 22 )(開始開車了),通過上圖,你發現了什么?商為22,我們減了4次24,百位數字減兩次,十位數字減兩次,最后余22,這就比開始我們減了22次要快多了吧。所以我們只需要使 被除數與除數位數相同,然后相減就可以了,(例如550 - 240 -240 - 24 - 24 = 22),位數不同時在除數后面補0。例如: 53 - 8,要用5-8,先補位,變成53-80,因為倒置了,即35-08,最后計算過后得到的結果是商為06,余數為05,去除前綴0 ,就得到最終結果了。
?? 如果你理解了上面的思路,那么現在咱們來詳細的分析一下大數除法的實現過程:
? ? 4.? 對得到的結果進行去除前綴0操作,輸出結果。
代碼如下:
#include<stdio.h> #include<string.h>char a[100],b[100];//用兩個字符串用來輸入兩個大數int x[100],y[100],z[100],m[100];//被除數 除數 商 余數int digit; //大數的位數void sub(int x[],int y[],int len1,int len2)//大數減法 {int i;for(i=0;i<len1;i++){if(x[i]<y[i]){x[i]=x[i]+10-y[i];x[i+1]--;}elsex[i]=x[i]-y[i];}for(i=len1-1;i>=0;i--)//判斷減法結束之后,被除數的位數{if(x[i]){digit=i+1;break;}} } int judge(int x[],int y[],int len1,int len2) {int i;if(len1<len2)return -1;if(len1==len2)//若兩個數位數相等{for(i=len1-1;i>=0;i--){if(x[i]==y[i])//對應位的數相等continue;if(x[i]>y[i])//被除數 大于 除數,返回值為1return 1;if(x[i]<y[i])//被除數 小于 除數,返回值為-1return -1;}return 0;//被除數 等于 除數,返回值為0} } int main() {int i,j=0,k=0,temp;int len1,len2,len;//len兩個大數位數的差值while(~scanf("%s %s",a,b)){len1=strlen(a);//被除數位數len2=strlen(b);//除數位數for(i=len1-1,j=0;i>=0;i--)//將字符串中各個元素倒序儲存在數組中{x[j++]=a[i]-'0';}for(i=len2-1,k=0;i>=0;i--){y[k++]=b[i]-'0';}if(len1<len2)//當被除數位數 小于 除數位數時{printf("商是:0\n");printf("余數是:");puts(a);}else //當被除數位數 大于或者等于 除數位數時{len=len1-len2;//兩個大數位數的差值for(i=len1-1;i>=0;i--)//將除數后補零,使得兩個大數位數相同。{if(i>=len)y[i]=y[i-len];elsey[i]=0;}len2=len1;//將兩個大數數位相同digit=len1; //將原被除數位數賦值給digitfor(j=0;j<=len;j++){z[len-j]=0;while(((temp=judge(x,y,len1,len2))>=0)&&digit>=k)//判斷兩個數的大小以及被除數位數與除數原位數的關系{sub(x,y,len1,len2); //大數減法函數z[len-j]++;//儲存商的每一位len1=digit;//重新修改被除數的長度if(len1<len2&&y[len2-1]==0)len2=len1; //將len1長度賦給len2;}if(temp<0)//若被除數 小于 除數,除數減小一位。{for(i=1;i<len2;i++)y[i-1]=y[i];y[i-1]=0;if(len1<len2)len2--;}}printf("商是:");for(i=len;i>0;i--)//去掉前綴0{if(z[i])break;}for(;i>=0;i--)printf("%d",z[i]);printf("\n");printf("余數是:");for(i=len1;i>0;i--){if(x[i])break;}for(;i>=0;i--)printf("%d",x[i]);printf("\n");}}return 0; }大數加法:https://blog.csdn.net/ysz171360154/article/details/85006990
大數減法:https://blog.csdn.net/ysz171360154/article/details/88916100
大數乘法:https://blog.csdn.net/ysz171360154/article/details/88918627
總結
以上是生活随笔為你收集整理的大数除法——超详细讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: yolov3算法模型P-R曲线绘制教程(
- 下一篇: python arp断网攻击_arp断网