c语言溢出该怎么算,解决整数运算溢出方法——C语言
嗨,大家好,這是我的第二篇博文,歡迎來踩
,留在你們的小腳印呀!
正如大家所知,在C語言中整型變量用4個字節(jié)表示,表示范圍略大于2乘以10的9次方,而長整型用8位表示,表示范圍略小于2乘以10
的19次方。如果所要計(jì)算的數(shù)字或者計(jì)算的中間變量超過整型表示范圍,則會出現(xiàn)錯誤結(jié)果,所以應(yīng)該想辦法避免這種錯誤的發(fā)生。
現(xiàn)在我們來看兩個簡單的例子:
A)輸入n,計(jì)算S=1!+2!+3!+4!+。。。+n!的末6位(不含前導(dǎo)0)。n<=10的6次方。這里,n!表示前n個正整數(shù)之積。
樣例輸入:10
樣例輸出:37913
分析:如果按照以前的思路,先依次求算階乘,再相加求和,再求除以1000000的余數(shù),顯然不可行。因?yàn)?000!早已超出長整型的表示范圍,所以計(jì)算機(jī)是無法幫你表示出1000000!數(shù)值的,需要再次審題,找到突破口。發(fā)現(xiàn),題目讓我們求算末6位,對于加法、減法、乘法的整數(shù)表達(dá)式除以正整數(shù)n
的余數(shù),可以在每步計(jì)算之后對n取余,結(jié)果不變。這就是我們要用到的有利條件。
基于這個思路,可以寫出正確的編程代碼如下:
#include
#include
int main(){
const int MOD=1000000;
int i,j,n,S=0,f;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
f=1;
for(j=1;j<=i;j++){
f=f*j%MOD;
}
S=(S+f)%MOD;
}
printf("%d\n",S);
printf("Time used=%.2lf\n",(double)clock()/CLOCKS_PER_SEC);
return 0;
}
通過多測輸入測試,我們可以發(fā)現(xiàn)一個問題,當(dāng)輸入數(shù)字大于等于25的時候,輸出結(jié)果都是一樣的820313,仔細(xì)分析的朋友可能已經(jīng)知道原因了,前25個數(shù)字相乘的結(jié)果有6個0,所以再對1000000取余沒有影響,結(jié)果相同。
B)輸入不超過1000的正整數(shù)n,輸出n!=1*2*3*4*.....*n的精確結(jié)果。
分析:細(xì)讀題目,發(fā)現(xiàn)這道題好像沒有上道題那么有突破點(diǎn),顯然中間結(jié)果會溢出,這該如何解決?換個思路,我們第一次學(xué)習(xí)乘法的時候是怎么做算術(shù)題的?對,列豎式,這道題可以模擬小學(xué)生算術(shù)題那樣列算式求解。
用一個足夠大的數(shù)組來存放要輸出的結(jié)果,各元素初始化為0,只有第一個元素初始化為1,因?yàn)閺?開始相乘。
這里f[0]表示個位,f[1]表示十位,f[2]表示百位,f[3]表示千位,依次遞增一個數(shù)量級。
源代碼如下:
#include
#include
const int
maxn=3000;//注意估計(jì)1000!大約等于4*10的2567次方,所以用3000個數(shù)組長度預(yù)存結(jié)果
int f[maxn];
int main(){
int i,j,n;
scanf("%d",&n);
memset(f,0,sizeof(f));
f[0]=1;
for(i=1;i<=n;i++)
{
int c=0;int sum=0;
for(j=0;j
{
sum=i*f[j]+c;
f[j]=sum;
c=sum/10;
}
}
for(j=maxn-1;j>=0;j--){
if(f[j])break;
}
for(i=j;i>=0;i--){
printf("%d",f[i]);
}
return 0;
}
不信的朋友可以試一試:輸入30
輸出265252859812191058636308480000000
這是長整型無法表示的整數(shù),我們卻讓計(jì)算機(jī)幫我“手算”出來了,夠朋友!
今天就寫到這里,下周再見!
總結(jié)
以上是生活随笔為你收集整理的c语言溢出该怎么算,解决整数运算溢出方法——C语言的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 九九乘法表c语言编程伪代码,py_11分
- 下一篇: c语言ad采样程序思路,单片机AD采样程