① 為防止溢出,c語言中應該如何定義變數
給你個求階乘的小程序,只要最大結果位數不超過20000就行。這種超大規模的階乘是不能用簡單的long保存的。位數太大了。
#define M 20000 /* 最大結果位數,DOS能訪問的內存有限,最好不要超過 30000 位*/
#define N (M+5)
main()
{
int Num;
register int i,j,k,flag;
register unsigned int n,m,pc;
unsigned char str_n[5],result_0[N],result_1[N];
void fun_print_result(char *result,int flag);
int fun_mul(char *a,char *b,char *c,int flag);
printf("輸入計算其階乘的數:Num = ");
scanf("%d",&Num);
if(Num >= 100)
{
printf("\n正在進行階乘運算. . .\n");
printf("已完成 00000 的階乘,請等待. . .");
}
for (j=0;j<N;j++)
{
result_1[j] = 0; result_0[j] = 0;
}
result_1[N-1] = 1;
for(i=0;i<5;i++)
{
str_n[i] = 0;
}
n = 1;
pc = 0; flag = N-1;
while (n <= Num)
{
m = n;
k = 4;
while(m > 0)
{
str_n[k] = m%10; m /= 10; k--;
}
if (pc%2 == 0)
{
if(fun_mul (str_n,result_1,result_0,flag) != 1)
{
printf("\n\n結果溢出!當前所設置的最大結果為 %d 位 已完成 %d 的階乘",M,pc);
exit(0);
}
}
else
{
if(fun_mul (str_n,result_0,result_1,flag) != 1)
{
printf("\n\n結果溢出!當前所設置的最大結果為 %d 位 已完成 %d 的階乘",M,pc);
exit(0);
}
}
flag = flag-(4-k); /* flag 標記相乘後「可能的」第一個有效數字的標號 */
if(pc%2 == 0) /* 再處理一次使 flag 正好標記第一個有效數字的標號 */
{
if(result_0[flag] == 0) flag++;
}
else
{
if(result_1[flag] == 0) flag++;
}
n++; pc++;
if((pc)%25 == 0 && Num >= 100 && pc >= 100)
{
printf("\r已完成 %5d",pc);
}
}
if(Num >= 100) printf("\n");
if ((pc-1)%2 == 0)
{
fun_print_result (result_0,flag);
}
else
{
fun_print_result (result_1,flag);
}
}
int fun_mul(char *a,char *b,char *c,int flag) /* 相乘函數 */
{
register int i,j;
for(j=flag;j<N;j++) c[j]=0;
for(i=4;i>=0;i--)
{
if(a)
{
for (j=N-1;j>=flag;j--)
{
if(b[j])
{
c[i+j-4] += a[i]*b[j];
}
if(c[i+j-4] > 9)
{
c[i+j-5] += c[i+j-4]/10; c[i+j-4] %= 10;
}
}
}
}
if(flag < 10)
{
if (c[0] || c[1] || c[2] || c[3] || c[4]) /*** 結果溢出判斷 ***/
{
return 0;
}
}
return 1;
}
void fun_print_result(char *result,int flag) /* 輸出結果函數 */
{
int p;
printf("\n本次計算結果共有 %d 位,如下:\n\n",N-flag);
for(p=flag;p<N-1;p++)
{
printf("%d",result[p]);
if((p+1-flag)%(21*80) == 0)
{
printf("\n計算結果太長,請按任一鍵看下一屏,Esc 退出");
if(getch() == 27)
{
clrscr(); exit(0);
}
clrscr();
}
}
printf("%d",result[N-1]);
printf("\n\n[OK]");
}
② 請教C語言高手,你們是如何防止數據計算溢出的
根據數據類型和計算結果范圍,選擇合適的數據類型。
另外一種方式就是對輸入數據進行限定,保證運算不會出現越界的可能。
還有一些其它復雜的計算方式,這里就不給你做介紹了
③ 在c語言編程中,如何避免整數運算溢出問題
C語言編譯時不會檢查數據溢出問題,需要編程者自行注意數據溢出問題。而且據我的經驗數據溢出問題會頻繁出現在初學習當中,程序寫多了就很少出現這樣的問題了。
④ C語言中在階乘的程序中如何避免中間結果溢出
使用數組吧,數組的地址是連續的,所以你只需加個判斷就可以了,當地位溢出時,高位自動加一的操作,最後想輸出結果,那就遍歷數組的所以位數,求出來就可以了
⑤ c語言中數據溢出的問題怎麼解決
需要准備的材料分別有:電腦、C語言編譯器。
1、首先,打開C語言編譯器,新建一個初始.cpp文件,例如:test.cpp,輸入問題基礎代碼。
⑥ C語言編程中為了防止數據的溢出,如果超過了long類型的值域,該如何處理謝謝了
為了防止數據的溢出,如果超過了long類型的值域,應該讓long類型與實型數據混合運算,這樣,根據不同類型數據混合運算的規則,轉化為高位元組再運算。
⑦ c語言數據溢出怎麼辦
C語言的強大之處就在於他的靈活性,程序員自己把握。編譯器可以幫助預防錯誤,但有些程序會利用溢出,所以溢出不完全是錯誤的事情。
1、溢出:
數據類型超過了計算機字長的界限而出現的數據溢出;
2、溢出可能原因:
當應用程序讀取用戶數據,復制到應用程序開辟的內存緩沖區中,卻無法保證緩沖區的空間足夠時 (假設定義數組int Array[10], 而在調用時使用Array[11] 或存放的數據超過int類型容量等), 內存緩沖區就可能會溢出.
3、溢出因素分析:
由於C/C++語言所固有的缺陷,既不檢查數組邊界,又不檢查類型可靠性,且用C/C++語言開發的程序由於目標代碼非常接近機器內核,因而能夠直接訪問內存和寄存器,只要合理編碼,C/C++應用程序在執行效率上必然優於其它高級語言。然而,C/C++語言導致內存溢出問題的可能性也要大許多。
⑧ C語言中char型數據計算後溢出,怎麼處理
無符號char
類型能標示的數是:0-255
有符號char類型能標示的數是:-128-127
C中調用積運算符之後做溢出檢測已經太晚,但調用和運算符之後做檢測則一點也不遲,所以可以通過對和運算結果的檢測實現能檢測溢出的積運算,因為 a * b 既是a個b的和:-5000000 * 1374389539 等於 -(5000000 * 1374389539)。括弧里是 5000000 個 1374389539 的和。
(8)c語言程序如何避免計算溢出擴展閱讀:
在 C 和 C++ 語言本身中,這個問題是不容易解決的。該問題基於 C 語言的根本設計決定(特別是 C 語言中指針和數組的處理方式)。由於 C++ 是最兼容的 C 語言超集,它也具有相同的問題。存在一些能防止這個問題的 C/C++ 兼容版本,但是它們存在極其嚴重的性能問題。而且一旦改變 C 語言來防止這個問題,它就不再是 C 語言了。許多語言(比如 Java 和 C#)在語法上類似 C,但它們實際上是不同的語言,將現有 C 或 C++ 程序改為使用那些語言是一項艱巨的任務。
⑨ C語言中怎麼處理溢出
C
中調用積運算符之後做溢出檢測已經太晚,但調用和運算符之後做檢測則一點也不遲,
所以你可以通過對和運算結果的檢測實現能檢測溢出的積運算,因為
a
*
b
既是
a
個
b
的和:
-5000000
*
1374389539
等於
-(5000000
*
1374389539)。括弧里是
5000000
個
1374389539
的和。
我把能檢測溢出的和運算包在
add(
)
里,然後在
multiply(
)
里重復調用
add(
)。
add(
)
怎麼檢測溢出?
和運算的結果若溢出將導致數值的環繞。上溢導致往下環繞,下溢導致往上環繞。
邊界狀況:
(1)最輕微的上溢是
INT_MAX
+
1
:結果是
INT_MIN。
(2)最嚴重的上溢是
INT_MAX
+
INT_MAX
:結果是
-2。
(3)最輕微的下溢是
INT_MIN
-
1
:結果是
INT_MAX。
(4)最嚴重的下溢是
INT_MIN
-
INT_MIN
:結果是
0。
結論:
(1)所有上溢結果都小於任何一個操作數。
(2)所有下溢結果都大於任何一個操作數。
所以
add(
)
可以用結果和任意選定的一個參數判斷溢出,並以落選的參數判斷溢出的方向。
add(
)
無法以返回值舉報溢出,所以採用
strtol(
)
的舉報方法。
不同於
strtol(
)
的是,若沒有溢出,add(
)
會把
0
賦值給
errno。
multiply(
)
在這方面跟
add(
)
一樣。
#include<stdio.h>
#include<errno.h>
/*
errno,
ERANGE
*/
/*
*
Returns
the
sum
of
a
and
b,
with
overflow
and
underflow
check.
*
If
overflow
or
underflow
occurred,
sets
errno
to
ERANGE,
else
to
0.
*/
int
add(
int
a,
int
b
)
{
int
result
=
a
+
b;
if(
b
>
0
&&
result
>
a
||
b
<=
0
&&
result
<=
a
)
errno
=
0;
else
errno
=
ERANGE;
return
result;
}
/*
*
Returns
the
proct
of
a
and
b
obtained
through
repeated
call
of
add(
).
*
Affects
errno
exactly
as
add(
)
does.
*/
int
multiply(
int
a,
int
b
)
{
int
sign_of_a
=
1,
result
=
0,
i
=
0;
/*
Keep
the
sign
of
multiplier
off
the
loop
sentinel.
*/
if(
a
<
0
)
{
sign_of_a
=
-1;
a
*=
-1;
}
/*
Have
to
reset
errno
here
because
it
won't
be
updated
if
a
is
0.
*/
errno
=
0;
while(
i++
<
a
)
{
result
=
add(
result,
b
);
if(
errno
==
ERANGE
)
break;
}
return
result
*
sign_of_a;
}
int
main(
)
{
int
result;
/*
Operands
too
huge:
sure
overflow.
*/
result
=
multiply(
-5000000,
1374389539
);
if(
errno
==
ERANGE
)
perror(
"Uh
oh"
);
else
printf(
"%d\n",
result
);
/*
Small
operands:
safe.
*/
result
=
multiply(
49,
-972
);
if(
errno
==
ERANGE
)
perror(
"Uh
oh"
);
else
printf(
"%d\n",
result
);
}
當然,應付溢出的最佳方法還是防範:充分了解數據的范圍,選擇恰當的變數類型。
也許你正考慮改用不需要你擔心整數類型溢出的語言。考慮過
Python
嗎?
⑩ c語言算術溢出問題怎麼解決
首先,這是警告,告訴你有可能產生溢出風險,並不是一定會發生溢出。
其次,底下已經告訴你了,要強制轉換一下……
sqrt(i+(long int)100);