posts - 134,comments - 22,trackbacks - 0

          網上流行的一份C++筆試題目中有這樣一個題目(最初出處未知,從google或者baidu可搜索到多出來源)

          10. 以下兩條輸出語句分別輸出什么?[C++]
          float a = 1.0f;
          cout << (int)a << endl;
          cout << (int&)a << endl;
          cout << boolalpha << ( (int)a == (int&)a ) << endl; //
          輸出什么?

          float b = 0.0f;
          cout << (int)b << endl;
          cout << (int&)b << endl;
          cout << boolalpha << ( (int)b == (int&)b ) << endl; //
          輸出什么?

          這個題目涉及float在計算機中的存儲問題,IEEE 754的標準就是描述的這個問題。如果這個題目放在筆試的時候應該比面試的時候容易多了。

          這個題目的幾個答案為110653532160x3f800000H),false00true。如果你已完美的答出這六個答案,就可以忽略后面的內容。

          1.我們先來看一下IEEE 754中關于floatdouble的存儲規范。

          無論是單精度還是雙精度在存儲中都分為三個部分:

          1. 符號位(Sign) : 0代表正,1代表為負

          2. 指數位(Exponent:用于存儲科學計數法中的指數數據,并且采用移位存儲

          3. 尾數部分(Mantissa):尾數部分

          其中float的存儲方式如下圖所示:

           

          指數部分(E) 占用8-bit的二進制數,可表示數值范圍為0255。 但是指數應可正可負,所以IEEE規定,此處算出的次方須減去127才是真正的指數。所以float的指數可從 -126128.

          尾數部分(M)實際是占用24-bit的一個值,由于其最高位始終為 1 ,所以最高位省去不存儲,在存儲中只有23-bit

          符號位:s 通過(-1)的s次冪來表示正負號。

          而雙精度的存儲方式為:

          double

          1bit(符號位)

          11bits(指數位)

          52bits(尾數位)


          我們把EM從二進制串表示轉換為真正的em
          這里要涉及到規格化(normalized)”非規格化(denormalized)”規格化與否全看指數E下面分三種情況討論E,并分別計算em:
          1、規格化:當E的二進制位不全為0,也不全為1時,N為規格化形式。此時e被解釋為表示偏置(biased)形式的整數,e值計算公式如下圖所示:

           

          上圖中,|E|表示E的二進制序列表示的整數值,例如E"10000100",|E|=132,e=132-127=5 k則表示E的位數,對單精度來說,k=8,bias=127,對雙精度來說,k=11,bias=1023

          此時m的計算公式如下圖所示:

           

          標準規定此時小數點左側的隱含位為1,那么m=|1.M|。如M="101",則|1.M|=|1.101|=1.625, m=1.625

          2、非規格化:當E的二進制位全部為0時,N為非規格化形式。此時em的計算都非常簡單。


          注意,此時小數點左側的隱含位為0   為什么e會等于(1-bias)而不是(-bias),這主要是為規格化數值、非規格化數值之間的平滑過渡設計的。后文我們還會繼續討論。有了非規格化形式,我們就可以表示0了。把符號位S1,其余所有位均置0后,我們得到了 -0.0; 同理,把所有位均置0,則得到 +0.0。非規格化數還有其他用途,比如表示非常接近0的小數,而且這些小數均勻地接近0,稱為逐漸下溢(gradually underflow)”屬性。
          3、特殊數值:當E的二進制位全為1時為特殊數值。此時,若M的二進制位全為0,則n表示無窮大,若S1則為負無窮大,若S0則為正無窮大; M的二進制位不全為0時,表示NaN(Not a Number),表示這不是一個合法實數或無窮,或者該數未經初始化。

          2.問題的解答

          對于1.0f這個數字,我們應該如何表示?按照上面的規則可以得到,符號位為0,指數位為1270x7F),尾數部分M應該為全0。因此它在計算機中的存儲就是0x3F800000H

          cout << (int)a << endl;

          a從浮點數轉換為整數,由于1.0f能夠使用32bits完整的表示,沒有舍入誤差,因此會輸出整數 1
          cout << (int&)a << endl;

          a里面的內容轉換為整數地址,因此編譯器會直接浮點數的32位表示直接輸出,,即0x3f800000h10進制表示。

          對于0.0f這個特殊的表示上面已經提到了,它在內存中的存儲就是全0,因此直接把浮點數轉換為整數還是直接把浮點數的表示轉化為整數地址結果都是0

          正如上面提到的一樣,浮點數-0的表示和+0的表示是不同的,-0在內存中的表示為0x80000000H

          最后再轉載一點關于long double的知識,我也沒有自己深入。

          3.擴展雙精度格式(long double)

          擴展雙精度格式(SPARC 結構計算機)

          4倍精度浮點環境符合IEEE關于擴展雙精度格式的定義。該浮點環境的4倍精度浮點格式共128位,占4個連續32位字,包含3個構成字段:112位的小數f15位的偏置指數e,和1位的符號s。將這4個連續的32位字整體作為一個128位的字,進行重新編號。其中0110位包含小數f112126位包含偏置指數e;第127位包含符號位s。如圖3所示

          SPARC結構計算機中,地址最高的32位字存放小數的32位最低有效位,即f[31:0];但是在PowerPC結構計算機中,卻是地址最低的32位字存放這些位

          緊鄰的兩個32位字(在SPARC機中向下計算,在PowerPC機中向上計算)分別存放f[63:32]f[95:64]

          最后一個字的第015位存放小數的最高16,f[111:96]。其中第0位存放該16位的最低有效位,第15位存放整個小數f的最高有效位。第1630位存放15位的偏置指數e,其中第16位存放偏置指數的最低有效位,第30位存放它的最高有效位。最高位,第31位存放符號s

          擴展雙精度格式(Intel x86結構計算機)

          該浮點環境雙精度擴展格式符合IEEE雙精度擴展格式的定義。該浮點環境的擴展雙精度格式共80位,占3個連續32位字,包含四個構成字段:63位的小數f1位顯式前導有效位(explicit leading significand bitj15位偏置指數e,和1位符號位s。將這3個連續的32位字整體作為一個96位的字,進行重新編號。其中063包含63位的小數f,第63位包含前導有效位j6478位包含15位的偏置指數e,最高位第79位包含符號位s

          Intel結構系計算機中,這些字段依次存放在十個連續的字節中。但是,由于 UNIX  System V Application Binary Interface Intel 386 Processor Supplement (Intel ABI) 要求雙精度擴展參數,從而占用堆棧中3個相連地址的32位字,其中最高一個字的高16位未被使用

          地址最低的32位字存放小數f的低32位,即f[31:0]。其中第0位存放整個小數f的最低有效位LSB 31位存放小數低32位的最高有效位MSB

          地址居中的32位字,第030位存放小數f31位最高位,即f[62:32]。其中第0位存放31位最高小數位的最低有效位LSB,第30位存放整個小數的最高有效位,地址居中的32位字的最高位第31位存放顯式的前導有效位j

          地址最高32位字里,第014位存放15位的偏置指數e,第0位存放偏置指數的最低有效位LSB,第14位存放最高有效位MSB,第15位存放符號位s。雖然地址最高的32位字的高16位在Intel x86結構系列機種未被使用,但他們對符合Intel ABI的規定來說,是必需的

           原文地址 http://blog.csdn.net/abortexit/archive/2009/06/22/4288279.aspx
          posted on 2009-12-10 15:51 何克勤 閱讀(401) 評論(0)  編輯  收藏 所屬分類: C/C++
          主站蜘蛛池模板: 汕头市| 稻城县| 巫溪县| 宁晋县| 新闻| 拉孜县| 成都市| 霍州市| 澎湖县| 辽源市| 福泉市| 桐城市| 孟州市| 昭苏县| 故城县| 鞍山市| 肇源县| 永吉县| 武强县| 永清县| 泽普县| 治多县| 兴安县| 城口县| 彭泽县| 抚宁县| 江达县| 礼泉县| 全椒县| 和政县| 梁平县| 武邑县| 福清市| 青川县| 娱乐| 通榆县| 武城县| 达日县| 济阳县| 德州市| 揭西县|