這道題主要考察了面試者對浮點數存儲格式的理解。另外,請不要討論該題本身是否有意義之類的話題。本題只為了測試面試者相關的知識是否掌握,題目本身並沒有實際的意義。
下面有6個浮點類型變量,其中前三個是float類型的,后三個是double類型的。題目的代碼如下:
float f_v1 = 20; float f_v2 = 20.3; float f_v3 = 20.5; double d_v1 = 20; double d_v2 = 20.3; double d_v3 = 20.5; cout << ((f_v1 == d_v1)?"true":"false") << endl; cout << ((f_v2 == d_v2)?"true":"false") << endl; cout << ((f_v3 == d_v3)?"true":"false") << endl;
問題有如下三個:
- 本題的運行結果是什么
- 請根據本題的運行結果解釋其原因
- 如果某個cout語句的輸出結果為false,在不改變變量定義語句的前提下,如何扔棄相等呢?
下面我先簡要說說如何解答本題,最后再給出答案。
首先應先了解float和double的存儲方式。這里先拿float為例。float一共占4個字節,共32位。分為3部分:符號位、指數位和尾數位。分別占1位、8位和23位,存儲結構如圖1所示。
圖1
其中如果浮點數為正值,符號位為0,否則為1。指數位采用移位存儲,也就是如果表示10^4,需要將4與127(二進制是01111111)相加存入指數位。尾數位決定了float的精度。尾數一共23位,最多可以表示8388607個值,由於沒有到9999999,所以float的精度為6,如果表示的數小於8388608,那么精度可到7位。這也是為什么有的書中說float的精度是6到7位的原因。這里並不是所有的數都能精確到7位。
另外,所謂的精度是指科學計數法E前面的數字的小數個數。例如,1.2345678E10。
這個數用float表示是可以精確到7位,因為2345678小於8388608。如果是1. 9388648E10,那么就只能精確到6位了。
如果理解了這個,還需要了解如何將十進制浮點數轉換為二進制浮點數,別告訴我你不會,如果真不會的話,回大學從念吧。總之,浮點數轉換是分別轉換整數和小數部分。整數部分除2,小數部分乘2。例如,20.5轉換為二進制是10100.1,20.3轉換為二進制如下:
10100.0100110011001...1001
其中“...”表示1001部分無限循環。也就是說20.3轉換為二進制浮點數是一個而無限循環的二進制浮點數。
最后,需要知道如何用科學計數法表示二進制浮點數(長見識了吧,二進制也可以用科學計數法)。20.5的科學計數法表示是:1.01001E100
20.3的科學計數法表示是:1.0100010011001...E100
現在就可以一個蘿卜一坑個了,將對應的數填入圖1的三個區域吧。
現在將20.5和20.3都存入double類型的變量,就可以一下看出本題的結果了。double占64位,8個字節。符號位占1位,指數位占11位,尾數位占52位。精度是15或16,原理和float一樣。
現在公布一下答案:
true
false
true
如果還沒理解其中的奧秘,可以看詳細的視頻講解。