精華區beta ESOE-90 關於我們 聯絡資訊
先看一個比較有趣的程式... /*************************************************************/ # include <stdio.h> int main() { float x; int i; printf("Input a real number...\n"); if (scanf("%f", &x) < 1) exit(1); for (i = sizeof x * 8 - 1; i >= 0; i--) putchar((*(int *)&x & 1 << i) ? '1' : '0'); putchar('\n'); return 0; } /*************************************************************/ 上面那是個小小的程式. 用來印出一個 IEEE 754 浮點數所具有的二進位格式. 好比說 1.53 - 00111111110000111101011100001010 早上我看到大部分的同學都卡在一個問題上頭... 『實數要怎麼對另一個實數取餘數?』 然而, 實數是不能取餘數的(就數學上來說, 那沒有意義. ) 在數學裡頭只有整數對整數才會有餘數(餘數的定義). 因此... % (modulus operator) 這個運算子只能用在整數上頭. 也就是 (int) % (int) 才可以. 像是 19 % 4 == 3, 3 % 2 == 1 等等... 而 3.7 % 1.2, 5.54 % 0.37 都是不對的. 所以, 當我們要把 180.00cm 轉成 5ft 10.87in 的時候. 要考慮到的是倍數關係... 海豹弄了個好玩的寫法... 因為題目中所有的值放大一百倍之後都會變成整數. 於是他先把 180.00(cm) 乘上 100. 對 3048 取餘數之後再除以 100... 這個值就當作英呎. 實際上這種作法的確行得通... 在電腦裡頭, 所有『有限位數』的實數(像是 Ex.3, 都為兩位小數)... 在實作上頭都是用整數表示. 只要記得輸出的時候把放大倍率(此例為 100)除回來. 不過這裡不用這麼費工夫... :) ANSI C 『規定』, 浮點數轉換為整數的時候, 是『捨去』小數部份. (int)3.142 == 3 (int)sqrt(2) == 1 這一些... 沒有例外. 以今天的練習來說... int h_ft; h_cm = 180; h_ft = h_cm / 30.48; 隨便到哪一台電腦上得到的答案都一樣是 h_ft == 5. 順帶提到一點: 這種寫法, VC++ 會給 warning... 它會希望你寫 h_ft = (int)(h_cm / 30.48); 不過實際上這只是違反了 C++ 的原則(不是 C). VC++ 在這點做得很爛, 它把 C 跟 C++ 全搞在一起了... C 跟 C++ 在很多地方有著根本性的衝突... 不像一般人想的那麼簡單: C++ == Advanced C. 請千萬記得: Visual C++ 的 C warning 有劇毒. 那反過來說... 如果把 h_ft 由 int 改為 double 好不好? 我看到有同學是這樣寫的... double h_ft; h_ft = (int)(h_cm / 30.48); printf("%.0fft %.2fin\n", h_ft, h_in); 這個答案會對哦... 而它主要是因為 IEEE 754 的緣故(這回就不是 C 的規定了. :P) 浮點數的整數部份, 在不溢位的轉換過程當中, 剛好會被保留下來... 但是! 只有整數的部份不變而已, 小數部份可是會變動的. 不過在前面那個例子當中, 恰巧我們要捨棄小數點以下的數字. 所以答案會對... 可以的話, 最好還是用整數... 除了效率問題(浮點運算比較慢). 最主要是設計哲學上的考量. 『應該是甚麼, 它就要是甚麼. 』 這裡的英呎都是整數, 那麼它表現起來就要有整數的樣子. 不過提到這個哲學嘛, 要等底子好一點才談得起來了... :) -- 新詩練習:新鮮。踩破初春裡的狗大便;不經意的滄桑,滿溢著嫩黃的喜悅。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.224.161.253 ※ 編輯: Muscovy 來自: 61.224.161.253 (03/20 17:43)