提示
- 函數的參數和返回值最好是“一等公民”,如int、char或者double等。其他“非 一等公民”作爲參數和返回值要複雜一些。如果函數不需要返回值,則返回類型應寫成 void。
注意這裏的return是一個動作,而不是描述。
計算組合數
程序4-1 組合數(有問題)
long long factorial(int n){
long long m = 1;
for(int i = 1; i <= n; i++)
m *= i;
return m;
}
long long C(int n, int m)
{
return factorial(n)/(factorial(m)*factorial(n-m)));
}
提示
- 即使最終答案在所選擇的數據類型範圍之內,計算的中間結果仍然可能溢出。
- 對複雜的表達式進行化簡有時不僅能減少計算量,還能減少甚至避免中間結 果溢出。
- 一個簡單的方法是利用n!/m!=(m+1) (m+2)…(n-1)n。雖然不能完全避免中間結果溢出,但是對於題目給出的範圍已經可以保證得 到正確的結果了。代碼如下:
程序4-2 組合數
long long C(int n, int m) {
if(m < n-m) m = n-m;
long long ans = 1;
for(int i = m+1; i <= n; i++) ans *= i;
for(int i = 1; i <= n-m; i++) ans /= i;
return ans;
}
素數判定
編寫函數,參數是一個正整數n,如果它是素數,返回1,否則返回0。
提示
- 這種“判斷一個事物是否具有 某一性質”的函數還有一個學術名稱——謂詞(predicate),下面程序中將寫一個謂詞。
- :建議把謂詞(用來判斷某事物是否具有某種特性的函數)命名成“is_xxx”的 形式,返回int值,非0表示真,0表示假。
- 編寫函數時,應儘量保證該函數能對任何合法參數得到正確的結果。如若 不然,應在顯著位置標明函數的缺陷,以避免誤用。
程序4-3 素數判定(有問題)
//n=1或者n太大時請勿調用,n太大時的 理由則不明顯:i*i可能會溢出!
int is_prime(int n) {
for(int i = 2; i*i <= n; i++)
if(n % i == 0) return 0;
return 1;
}
程序4-4 素數判定(2)
int is_prime(int n)
{
if(n <= 1) return 0;
int m = floor(sqrt(n) + 0.5);
for(int i = 2; i <= m; i++)
if(n % i == 0) return 0;
return 1;
}