一、什么是高精度
? ? ? ?高精度本質(zhì)上是一種計(jì)算,由于int型和long long型的存儲的數(shù)據(jù)大小有限。在有符號定義的情況下,int型為2的31次方減1;在無符號定義的情況下,lint型為2的32次方。因此過于巨大的數(shù)無法展示,這就用到了高精度來計(jì)算,其原理為將很大的數(shù)一位一位存在數(shù)組中,最后輸出數(shù)組。
?
?
?
二、高精度加法
? ? ? ? 說起來也覺得有些可笑,但確實(shí)如此,高精度加法我們運(yùn)用的是小學(xué)的數(shù)列式來理解。
? ? ? ? ? ? ? ? ? ?
? ? ? ? ?如左圖所示,我們首先將1加7得8,6加7為13,1加6為7;然后發(fā)現(xiàn)13大于10,因此要進(jìn)1。所以,7需要加1變?yōu)?。寫成代碼如上右圖所示,給大家解釋一下吧,aar1數(shù)組表示1,6,7三位數(shù);arr2數(shù)組表示6,7,1三位數(shù),值得注意的一點(diǎn)是在數(shù)組中應(yīng)倒置這樣的話便于計(jì)算;arr3數(shù)組表示的是最后的結(jié)果。第一行代碼是將1加7相加得到的結(jié)果(一會兒再解釋為啥還要加arr3),第二行代碼是將大于10的部分交于數(shù)組的下一個(gè)變量(體現(xiàn)在數(shù)學(xué)中也就是進(jìn)位);第三行代碼是得出結(jié)果(如6加7得13,經(jīng)過此步后便得到3)。由于這只是得到某一位的結(jié)果,因此循環(huán)才能得到最終的結(jié)果,上面未解釋的arr3則是為了防止可能由于前一位進(jìn)1而導(dǎo)致本身不再是0。給大家上代碼理解一下吧。
# include <stdio.h>
# include <string.h>
int main ()
{
int max(int x,int y);
//利用字符串形式輸入,否則數(shù)字太大,整形放不下。
char ch1[505]="123",ch2[505]="123";
int arr1[505]={0},arr2[505]={0},arr3[505]={0};
scanf("%s",&ch1);scanf("%s",&ch2);
int sz1=strlen(ch1);int sz2=strlen(ch2);
//因?yàn)橐h(huán)相加,sz3求循環(huán)條件的,由于最后一位相可能大于10,因此先進(jìn)1
int sz3=max(sz1,sz2)+1;
//將字符串轉(zhuǎn)變?yōu)閿?shù)組形式存儲
for(int i=0;i<sz1;i++)
{
arr1[sz1-i]=ch1[i]-'0';
}
for(int i=0;i<sz2;i++)
{
arr2[sz2-i]=ch2[i]-'0';
}
//高精度加法主體
for(int i=1;i<=sz3;i++)
{
arr3[i]=arr3[i]+arr1[i]+arr2[i];
arr3[i+1]=arr3[i]/10;
arr3[i]=arr3[i]%10;
}
//判斷數(shù)組最后一位是否為0,不是的話減去0,并且sz3還應(yīng)大于0,否則可能什么結(jié)果也不輸出(當(dāng)輸入為0時(shí))
if(arr3[sz3]==0&&sz3>0) sz3--;
輸出
for(int i=sz3;i>0;i--)
{
printf("%d",arr3[i]);
}
return 0;
}
int max(int x,int y)
{
int f;
if(x>y) f=x;
else f=y;
return f;
}
?
?
?
三、高精度減法
? ? ? ? ? ? 高精度減法其實(shí)和加法差不多,不過需要注意的一點(diǎn)是應(yīng)先判斷大小,應(yīng)該用大的減小的,計(jì)算機(jī)不會算小的減大的,下圖是高精度減法主體。
? ? ? ? ? ? 高精度減法也是循環(huán)相減的,一位一位減。給大家解釋一下高精度減法主體的代碼吧,先判斷一下減數(shù)和被減數(shù)的大小關(guān)系,如果減數(shù)大于被減數(shù),需要進(jìn)一,也就是上一位的減數(shù)減一,而這一位加10,這就是第二三行代碼的意思,最后一行則是相減得到的數(shù),給大家上整體的代碼看看吧。
# include <stdio.h>
# include <string.h>
int main ()
{
int compare(char a1[10090],char a2[10090],int sz1,int sz2);
char a1[10090]="123",a2[10090]="123";
int b1[10090]={0},b2[10090]={0},b3[10090]={0};
scanf("%s",&a1);scanf("%s",&a2);
int sz1=strlen(a1);
int sz2=strlen(a2);
//比較大小
int m=compare(a1,a2,sz1,sz2);
//判斷是否改變兩個(gè)的位置
if(m==0)
{
char q[10090]="123";
strcpy(q,a1);
strcpy(a1,a2);
strcpy(a2,q);
}
int sz3=strlen(a1);
int sz4=strlen(a2);
//將字符串變?yōu)閿?shù)組形式
for(int i=0;i<sz3;i++)
{
b1[sz3-i]=a1[i]-'0';
}
for(int i=0;i<sz4;i++)
{
b2[sz4-i]=a2[i]-'0';
}
//高精度減法主體
for(int i=1;i<=sz3;i++)
{
if(b1[i]<b2[i])
{
b1[i+1]--;
b1[i]=b1[i]+10;
}
b3[i]=b1[i]-b2[i];
}
//判斷是否為0
while(b3[sz3]==0&&sz3>1) sz3--;
//判斷是否要變?yōu)樨?fù)數(shù)
if(m==0) printf("-");
//輸出0
for(int i=sz3;i>0;i--)
{
printf("%d",b3[i]);
}
return 0;
}
int compare(char a1[10090],char a2[10090],int sz1,int sz2)
{
if(sz1>sz2) return 1;
else if(sz1<sz2) return 0;
else
{
for(int i=0;i<sz1;i++)
{
if(a1[i]>a2[i]) return 1;
else if(a1[i]<a2[i]) return 0;
else continue;
}
}
}
?
?
?
四、高精度乘法
?高精度乘法的本質(zhì)也是利用小學(xué)數(shù)學(xué)的列式來解決問題? ??
? ? ??
? ? ? ? ? ??
?給大家解釋一下代碼吧,大家經(jīng)過高精度加法和高精度減法的代碼應(yīng)該也是對高精度了解的比較清楚了,給大家簡單介紹一下高精度乘法吧,如上左圖所示,假設(shè)a為一個(gè)數(shù)組b為一個(gè)數(shù)組,c為一個(gè)數(shù)組,通過上圖可以看出,乘法每一個(gè)相乘的結(jié)果的下標(biāo),為上面兩個(gè)的下標(biāo)之和減1;如c3中的2是a2和b2中2和2相加減1得,c4中的4是由a4和b1或者b4和c1中4和1相加減1得到的。這就是來源。下面則是我們來實(shí)現(xiàn)這個(gè)代碼,相同的是,這也是一個(gè)循環(huán)(嵌套循環(huán),大家可以看代碼),我只是把主體寫出。
# include <stdio.h>
# include <string.h>
int main ()
{
//定義變量
char a1[2005]="123";
char a2[2005]="123";
int b1[2005]={0},b2[2005]={0},b3[2005]={0};
scanf("%s",a1);scanf("%s",a2);
int sz1=strlen(a1);int sz2=strlen(a2);
//將字符串變?yōu)閿?shù)組
for(int i=0;i<sz1;i++)
{
b1[sz1-i]=a1[i]-'0';
}
for(int i=0;i<sz2;i++)
{
b2[sz2-i]=a2[i]-'0';
}
//循環(huán)條件
int sz3=sz1+sz2;
//循環(huán)主體
for(int i=1;i<=sz1;i++)
{
for(int j=1;j<=sz2;j++)
{
b3[i+j-1]=b3[i+j-1]+b1[i]*b2[j];
b3[i+j]=b3[i+j]+b3[i+j-1]/10;
b3[i+j-1]=b3[i+j-1]%10;
}
}
if(b3[sz3]==0&&sz3>0) sz3--;
//輸出
for(int i=sz3;i>0;i--)
{
printf("%d",b3[i]);
}
return 0;
}
?
?
?
? ?五、實(shí)例(求函數(shù)階乘和)
·
?文章來源地址http://www.zghlxwxcb.cn/news/detail-737214.html
?這里我用了洛谷的一道題來舉例,結(jié)合了高精度加法和高精度減法,還是比較有難度的。即使我們可以掌握高精度這個(gè)知識點(diǎn),但能AC這道題還是不容易的。先給大家上代碼再解釋吧。
?文章來源:http://www.zghlxwxcb.cn/news/detail-737214.html
# include <stdio.h>
int main ()
{
int n,cnt=1;scanf("%d",&n);
int a[10000]={0},b[10000]={0};
for(int i=0;i<10000;i++) a[i]=0;
for(int i=0;i<10000;i++) b[i]=0;
a[1]=1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=cnt;j++)
{
a[j]*=i;
}
for(int q=1;q<=cnt;q++)
{
if(a[q]<10) continue;
int x=q;
while(x<=cnt)
{
if(a[cnt]>9) cnt++;
a[x+1]=a[x+1]+a[x]/10;
a[x]=a[x]%10;
x++;
}
}
for(int h=1;h<=cnt;h++)
{
b[h]=a[h]+b[h];
if(b[cnt]>10) cnt++;
b[h+1]=b[h+1]+b[h]/10;
b[h]=b[h]%10;
}
}
for(int i=cnt;i>0;i--)
{
printf("%d",b[i]);
}
}
怎么說呢,這個(gè)解釋起來還是比較麻煩的,我們先輸入n,然后就進(jìn)入循環(huán)主體了,先for循環(huán)吧,將每一位數(shù)字都乘以i;然后再進(jìn)入另一個(gè)循環(huán),先判斷每一位數(shù)是否大于9,如果大,肯定要進(jìn)1,因此要進(jìn)入另一個(gè)循環(huán)。然后就是進(jìn)入一個(gè)while循環(huán),判斷最后一位是否大于9,如果大于,那么肯定要進(jìn),為防止溢出,我們就需要將數(shù)組加1,然后就是進(jìn)入高精度乘法主體,然后再進(jìn)入高精度加法主體,最后循環(huán)完輸出即可。
寫的不好,如果我有什么理解,一定會及時(shí)更改,謝謝各位的觀看。
?
?
到了這里,關(guān)于算法之高精度(含實(shí)例與詳解)C語言的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!