作者LPH66 (-6.2598534e+18f)
看板C_and_CPP
標題Re: [問題] 面試遇到的問題
時間Sat Aug 1 00:46:07 2015
※ 引述《caxz ( )》之銘言:
: 問題三
: int main()
: {
: float a = 0.7;
: if(a > 0.7) cout<< "C" <<endl;
: else cout<< "C++" <<endl;
: //以上這段印出C++
: if(a < 0.7)
: cout<< "C" <<endl;
: else
: cout<< "C++" <<endl;
: //以上這段印出C
: }
: 這看似簡單但我卻想不通....有什麼到原因是這樣的output ??
____
0.7 無法以二進位有限小數表示, 將其轉為二進位是為 0.10110
因此實際上電腦看到的不是 0.7, 而是依照其精確度留存的二進位近似值
取 float 切 24 位有效位數會得到 0.101100110011001100110011 | 0...
因此這個 a 變數實際上存的值是二進位的 0.101100110011001100110011
而單寫 0.7 其形態為 double, 切 53 位有效位數得
0.10110011001100110011001100110011001100110011001100110 | 0...
因此 a 跟 0.7 比較即是比較下列兩數的大小:
a 0.101100110011001100110011
0.7 0.10110011001100110011001100110011001100110011001100110
由此 a < 0.7 會成立
: 後來又被問到 如果 a 的行型態被改為 double 呢?
: 我剛剛是try了一下 結果都是C++
: 為何會有這種改變呢?
這時這兩個數都是 double 的那個 0.7
所以兩者相等, 兩個不等的比較都不成立
---
題外話, 這兩個數精確地轉回十進位是
float -> 0.699999988079071044921875
double -> 0.6999999999999999555910790149937383830547332763671875
---
既然這是面試題
我覺得你只要能答出前一種狀況會一個成立一個不成立
後一種狀況則會都不成立, 應該基本觀念就有了
(前一種狀況改不同的數結果會不同, 例如若改 0.6 則是 a > 0.6 成立
改 0.5 則是 a > 0.5 跟 a < 0.5 都不成立)
--
LPH [acronym]
= Let Program Heal us
-- New Uncyclopedian Dictionary, Minmei Publishing Co.
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 123.195.39.85
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1438361169.A.590.html
推 chrisdar: Q3 真的只是想考 有沒看過 IEEE754 而已吧~ 08/01 01:04
推 chrisdar: 更正, Q3 考的是 1.IEEE754 2.字面常量 08/01 01:07
→ Feis: IEEE 754 不是 C 或 C++ 的必備條件. 還是要看編譯器 08/01 01:08
推 stupid0319: 是在考組語fld,fcomip 怎麼運作的嗎? 08/01 01:09
→ Feis: 要我說的話應該就是對浮點數的危機感而已 08/01 01:09
推 chrisdar: 有些編譯器會提醒二元比較運算元 的 左右方資料寬度不同 08/01 01:12
→ chrisdar: 遇到不會提示的 debug起來真的就完全沒有頭緒 08/01 01:14
IEEE754 在這個回答裡只是當做二進位科學記號來看而已
浮點數這種東西就算實作不同, 骨子裡都還是科學記號 (這點原 PO 可以記下來)
因此一些科學記號的概念換個底就能通用, 例如有效數字、計算誤差等等
前一種狀況就算浮點數不是 IEEE754, 只要都是科學記號表示就一定會有一大一小
另外 chrisdar 提到的 literal fp 的型態算是隱藏考題
不知道這個的話後一種狀況跟前一種就沒有差別了
所以我才會說合格的回答是「前一種兩者恰有一成立,後一種兩者皆不成立」
※ 編輯: LPH66 (123.195.39.85), 08/01/2015 01:42:09
推 name2name2: 推 08/01 08:20
推 cuteSquirrel: 優質好文 08/01 10:18
推 EdisonX: 我想問一般在取有效位數是看後一位是 0/1 做 +1 嗎? 08/01 14:51
→ EdisonX: 像 0.0011 | 1 看4位,最後是 0.0011 / 0.0100 ? 08/01 14:51
推 OSDBNetwork: 高手中的高手 08/01 15:16
推 LiloHuang: 0.7f 08/01 15:25
→ Feis: EdisonX: "一般" 的話,預設是往偏差值少的地方移動 08/01 15:54
→ Feis: 如果往大往小都一樣, 則往雙數走. 這例子應該是 0.0100 08/01 15:55
→ Feis: 實際上的話應該還是看實作品. 無條件進位或捨去也都是可能 08/01 15:55
→ Feis: 如果要研究的話還有正負數可以玩呢~ 08/01 15:56
→ Feis: 有興趣的話可以複習一下 " 四捨六入五成雙" 08/01 16:01
推 Jkx: 08/01 17:56
推 EdisonX: 謝謝feis 08/01 21:30
推 kidbower: wow 08/02 22:38