//題目:輸入乙個大於3的整數n,判定它是否為素數(prime,又稱質數)
#include
#include
int main()
————譚浩強.《c程式設計》(第四版).p137,清華大學出版社
這個程式的**首先輸入需要判斷的整數並存放在變數n中(其實這個變數定義為unsigned型別更理想,因為題目中已經明確是大於3的整數)。緊接著通過:
k=sqrt(n);
試圖求出n的平方根或其平方根的整數部分。然而這個寫法是有問題的,能否正確地按照希望求得n的平方根或其整數部分是得不到保證的。
這是因為sqrt()函式的函式原型是:
double sqrt (double);
也就是說,sqrt()函式的引數和返回值都是double資料型別。double型別屬於浮點資料型別的一種,浮點型別並非像整數型別那樣可以精確地表示整數,正相反,浮點資料型別用於近似地表示實數,儘管在個別情況下可以精確地表示,但就一般意義上而言,浮點資料型別只是對一定範圍內的實數的一種近似表示。
因此,在k=sqrt(n)這個表示式中,不可能指望這個n是準確的,因為按照sqrt()函式原型的要求,這個n實際上表示的是(double)n,即呼叫時會存在型別轉換,轉換後的值為double型別,它是否精確等於原來的int型別的n值,一般而言是不清楚的。
或許有些對ieee754標準很熟悉的人對此不能贊同——他們非常清楚在這個標準下浮點數的表示方法和內部結構。好吧,「不爭論」,繼續看下乙個不確定性。
由於sqrt()函式的返回值是double型別,這表明sqrt()函式只承諾為我們求得實參的平方根的近似值——而不是像數學那樣一定可以得到乙個精確值。換句話說,當呼叫sqrt(9.)的時候,函式未必會精確地得到3.0這個數學上的精確的平方根,sqrt(9.)的值無論為3.000000000000001還是2.999999999999999 都有可能。這雖然是出於理性的判斷,但也並非絕無經驗事實作為佐證。試看下面的**:
#include #include int main( void )
在某些編譯器上的輸出結果是:
9999
這清楚地表明pow()這樣的返回值為double型別的數學函式只是一種近似計算的函式。sqrt()這個數學函式也是如此,sqrt(9.)的值無論為3.0、3.000000000000001還是2.999999999999999都有可能。一旦sqrt(9.)的值為2.999999999999999,那麼
k=sqrt(n);
for(i=2;i<=k;i++)
的迴圈次數就會產生錯誤。這種錯誤在何時出現很難預料,但k=sqrt(n)是乙個似是而非的表達則是確切無疑的。
這種未必立刻發作的錯誤比那些立刻就產生症狀的bug更可怕,它就像一顆不定時炸彈一樣說不定什麼時候造成損失。古代有則守株待兔的寓言,說的是某一天出現了兔子,你不能指望天天出現兔子。但這裡的情形恰恰相反,儘管很多天都沒出現兔子,但你保不准哪天就會突然竄出乙隻兔子。而一旦出現兔子,其嚴重後果則是你假定不會出現兔子時所無法預料的。
那麼此時應該如何求n的平方根或其整數部分呢?實際上可以利用下面的數學常識輕易求得:
1=1^2
1+3=2^2
1+3+5=3^2
…1+3+5+…+(2k1)=k^2
後面正確的**應用了這個原理。
樣本**中的另乙個問題是根本沒有考慮輸入一旦不小於3時應該如何處理,這樣的乙個嚴重後果是一旦使用者誤輸入資料,比如輸入了負數,程式將會發生悲慘的崩潰。在乙個真正的軟體中,絕對不能假設使用者一定會正確地輸入,否則可能帶來非常嚴重且無法彌補的損失。
此外,**中的輸出部分過於囉唆繁複,後面的**對此也進行了修正。
#include int main( void )
for(i=2;i<=k;i++)
if(n%i==0)
break;
printf("%d%s是素數\n" , n , (i > k)?"":"不");
} return 0;
}
其中:
while( n_ >= odd )
用於求出n的平方根的整數部分。由於只需進行√n次整數的加減法運算,其效率方面也必定高於浮點運算的k=sqrt(n)。
求職中七個似是而非的誤區
求職的艱難使得關於求職指導成為一種小小的熱門,而有些流行在求職場上的觀點卻是似是而非的,如果求職者輕易被這些觀點牽著鼻子走,那麼可能會在求職中碰壁。誤區一 找工作的人應避免那些正在解雇員工的公司,試想乙個減員的公司怎麼還會僱傭新人呢?而在現實生活中,這些公司可能恰好就是求職人的最佳去處。有許多這樣的...
似是而非的製造業 德魯克日誌之五月十二日
quote b 你如何讓更少的員工製造出更多的產品 b 在對2020年的眾多 中,人們認為最可能實現的莫過於以下論斷 屆時,發達國家的製造業總產量至少要翻一番,但是製造業的員工總人數將會比現在減少10 12 變革製造業並且推動其生產率迅速提高是一種全新的概念,例如精益生產等。製造業的新理念比資訊化和...
權利是人賦而非天賦的
課堂回顧 你好,今天我要給你介紹乙個既離經叛道又實事求是而且合情合理的觀念,那就是權利其實是人賦的,不是天賦的。上一講我跟你講了權利和能力之間的區別。我們說在動物世界裡面,動物有的只有能力,might 而在人類社會裡面,當然每個人有能力,而他們更重要的是有權利,right。能力取決於你自己能夠占有多...