欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#浮點數(shù)的表示和基本運算

 更新時間:2016年12月01日 00:06:50   投稿:mdxy-dxy  
這篇文章主要介紹了C#浮點數(shù)的表示和基本運算,需要的朋友可以參考下

1 浮點數(shù)的表示

通常,我們可以用下面的格式來表示浮點數(shù)

S P M

其中S是符號位,P是階碼,M是尾數(shù)

對于IBM-PC而言,單精度浮點數(shù)是32位(即4字節(jié))的,雙精度浮點數(shù)是64位(即8字節(jié))的。兩者的S,P,M所占的位數(shù)以及表示方法由下表可知

S P M 表示公式 偏移量
1 8 23 (-1)S*2(P-127)*1.M 127
1 11 52 (-1)S*2(P-1023)*1.M 1023

以單精度浮點數(shù)為例,可以得到其二進制的表示格式如下

S(第31位) P(30位到23位) M(22位到0位)

其中S是符號位,只有0和1,分別表示正負;P是階碼,通常使用移碼表示(移碼和補碼只有符號位相反,其余都一樣。對于正數(shù)而言,原碼,反碼和補碼都一樣;對于負數(shù)而言,補碼就是其絕對值的原碼全部取反,然后加1.)

為了簡單起見,本文都只討論單精度浮點數(shù),雙精度浮點數(shù)也是用一樣的方式存儲和表示的。

2 浮點數(shù)的表示約定

單精度浮點數(shù)和雙精度浮點數(shù)都是用IEEE754標準定義的,其中有一些特殊約定。

(1) 當P = 0, M = 0時,表示0。

(2) 當P = 255, M = 0時,表示無窮大,用符號位來確定是正無窮大還是負無窮大。

(3) 當P = 255, M != 0時,表示NaN(Not a Number,不是一個數(shù))。

當我們使用.Net Framework的時候,我們通常會用到下面三個常量

Console.WriteLine(float.MaxValue); // 3.402823E+38
Console.WriteLine(float.MinValue); //-3.402823E+38
Console.WriteLine(float.Epsilon);  // 1.401298E-45
//如果我們把它們轉(zhuǎn)換成雙精度類型,它們的值如下
Console.WriteLine(Convert.ToDouble(float.MaxValue)); // 3.40282346638529E+38
Console.WriteLine(Convert.ToDouble(float.MinValue)); //-3.40282346638529E+38
Console.WriteLine(Convert.ToDouble(float.Epsilon));  // 1.40129846432482E-45

那么這些值是如何求出來的呢?

根據(jù)上面的約定,我們可以知道階碼P的最大值是11111110(這個值是254,因為255用于特殊的約定,那么對于可以精確表示的數(shù)來說,254就是最大的階碼了)。尾數(shù)的最大值是11111111111111111111111。

那么這個最大值就是:0 11111110 11111111111111111111111。

也就是 2(254-127) * (1.11111111111111111111111)2 = 2127 * (1+1-2-23) = 3.40282346638529E+38

從上面的雙精度表示可以看出,兩者是一致的。最小的數(shù)自然就是-3.40282346638529E+38。

對于最接近于0的數(shù),根據(jù)IEEE754的約定,為了擴大對0值附近數(shù)據(jù)的表示能力,取階碼P = -126,尾數(shù) M = (0.00000000000000000000001)2 。此時該數(shù)的二進制表示為:0 00000000 00000000000000000000001

也就是2-126 * 2-23 = 2-149 = 1.40129846432482E-45。這個數(shù)字和上面的Epsilon是一致的。

如果我們要精確表示最接近于0的數(shù)字,它應(yīng)該是 0 00000001 00000000000000000000000

也就是:2-126 * (1+0)  =  1.17549435082229E-38。

3 浮點數(shù)的精度問題

浮點數(shù)以有限的32bit長度來反映無限的實數(shù)集合,因此大多數(shù)情況下都是一個近似值。同時,對于浮點數(shù)的運算還同時伴有誤差擴散現(xiàn)象。特定精度下看似相等的兩個浮點數(shù)可能并不相等,因為它們的最小有效位數(shù)不同。

由于浮點數(shù)可能無法精確近似于十進制數(shù),如果使用十進制數(shù),則使用浮點數(shù)的數(shù)學(xué)或比較運算可能不會產(chǎn)生相同的結(jié)果。

如果涉及浮點數(shù),值可能不往返。值的往返是指,某個運算將原始浮點數(shù)轉(zhuǎn)換為另一種格式,而反向運算又將轉(zhuǎn)換后的格式轉(zhuǎn)換回浮點數(shù),且最終浮點數(shù)與原始浮點數(shù)相等。由于一個或多個最低有效位可能在轉(zhuǎn)換中丟失或更改,往返可能會失敗。

4 將浮點數(shù)表示為二進制

4.1 無小數(shù)的浮點數(shù)轉(zhuǎn)換成二進制表示

首先,我們用一個不帶小數(shù)的浮點數(shù)來說明如何將一個浮點數(shù)轉(zhuǎn)換成二進制表示。假設(shè)要轉(zhuǎn)換的數(shù)據(jù)是45678.0f。

在處理這種不帶小數(shù)的浮點數(shù)時,直接將整數(shù)部分轉(zhuǎn)化為二進制表示:

1011001001101110.0,這時要加上一位默認的1(這是因為按照浮點數(shù)規(guī)格化的要求,尾數(shù)必須化成 1.M的格式),

那么可以表示成:11011001001101110.0。

然后將小數(shù)點向左移,一直移到離最高位只有1位,也就是 1.1011001001101110,一共移動了16位,我們知道,左移位表示乘法,右移位表示除法。所以原數(shù)就等于這樣:1.1011001001101110 * ( 216 )?,F(xiàn)在尾數(shù)和指數(shù)都出來了。因為最高位的1是根據(jù)標準加上去的,只是為了滿足規(guī)格化的要求,這時候需要把這個1去掉。尾數(shù)的二進制就變成了:1011001001101110。

最后在尾數(shù)的后面補0,一直到補夠23位,就是:10110010011011100000000。

再回來看指數(shù),根據(jù)前面的定義,P-127=16,那么P = 143,表示成二進制就是:10001111。

45678.0f這個數(shù)是正的,所以符號位是0,那么我們按照前面講的格式把它拼起來,就是:0 10001111 10110010011011100000000。

這就是45678.0f這個數(shù)的二進制表示,如果我們要得到16進制的表示,非常簡單,我們只需要把這個二進制串4個一組,轉(zhuǎn)換成16進制數(shù)就可以了。但是要注意的是x86架構(gòu)的CPU都是Little Endian的(也就是低位字節(jié)在前,高位字節(jié)在后),所以在實際內(nèi)存中該數(shù)字是按上面二進制串的倒序存儲的。要知道CPU是不是little endian的也很容易。

BitConverter.IsLittleEndian;

4.2 含小數(shù)的浮點數(shù)表示為二進制

對于含小數(shù)的浮點數(shù),會有精度的問題,下面舉例說明。假設(shè)要轉(zhuǎn)換的小數(shù)為123.456f。

對于這種帶小數(shù)的就需要把整數(shù)部和小數(shù)部分開處理。對于整數(shù)部分的處理不再贅述,直接化成二進制為:100100011。小數(shù)部份的處理比較麻煩一些,我們知道,使用二進制表示只有0和1,那么對于小數(shù)就只能用下面的方式來表示:

a1*2-1+a2*2-2+a3*2-3+......+an*2-n

其中a1等數(shù)可以是0或者1,從理論上將,使用這種表示方法可以表示一個有限的小數(shù)。但是尾數(shù)只能有23位,那么就必然會帶來精度的問題。

在很多情況下,我們只能近似地表示小數(shù)。來看0.456這個十進制純小數(shù),該如何表示成二進制呢?一般說來,我們可以通過乘以2的方法來表示。

首先,把這個數(shù)字乘以2,小于1,所以第一位為0,然后再乘以2,大于1,所以第二位為1,將這個數(shù)字減去1,再乘以2,這樣循環(huán)下去,直到這個數(shù)字等于0為止。

在很多情況下,我們得到的二進制數(shù)字都大于23位,多于23位的就要舍去。舍入原則是0舍1入。通過這樣的辦法,我們可以得到二進制表示:1111011.01110100101111001。

現(xiàn)在開始向左移小數(shù)點,一共移了6位,這時候尾數(shù)為:1.11101101110100101111001,階碼為6加上127得131,二進制表示為:10000101,那么總的二進制表示為:

0  10000101  11101101110100101111001

表示成十六進制是:42  F6  E9  79

由于CPU是Little Endian的,所以在內(nèi)存中表示為:79  E9  F6  42。

4.3 將純小數(shù)表示成二進制

對于純小數(shù)轉(zhuǎn)化為二進制來說,必須先進行規(guī)格化。例如0.0456,我們需要把它規(guī)格化,變?yōu)?.xxxx * (2n )的形式,要求得純小數(shù)X對應(yīng)的n可用下面的公式:
n = int( 1 + log 2X )

0.0456我們可以表示為1.4592乘以以2為底的-5次方的冪,即1.4592 * ( 2-5 )。轉(zhuǎn)化為這樣形式后,再按照上面處理小數(shù)的方法處理,得到二進制表示

1. 01110101100011100010001

去掉第一個1,得到尾數(shù)

01110101100011100010001

階碼為:-5 + 127 = 122,二進制表示為

0  01111010  01110101100011100010001

最后轉(zhuǎn)換成十六進制
11 C7 3A 3D

5 浮點數(shù)的數(shù)學(xué)運算

5.1 浮點數(shù)的加減法

設(shè)兩個浮點數(shù) X=Mx*2Ex ,Y=My*2Ey

實現(xiàn)X±Y要用如下5步完成:

(1)對階操作:小階向大階看齊
(2)進行尾數(shù)加減運算
(3)規(guī)格化處理:尾數(shù)進行運算的結(jié)果必須變成規(guī)格化的浮點數(shù),對于雙符號位(就是使用00表示正數(shù),11表示負數(shù),01表示上溢出,10表示下溢出)的補碼尾數(shù)來說,就必須是
001×××…×× 或110×××…××的形式
若不符合上述形式要進行左規(guī)或右規(guī)處理。
(4)舍入操作:在執(zhí)行對階或右規(guī)操作時常用“0”舍“1”入法將右移出去的尾數(shù)數(shù)值進行舍入,以確保精度。
(5)判結(jié)果的正確性:即檢查階碼是否溢出

若階碼下溢(移碼表示是00…0),要置結(jié)果為機器0;
若階碼上溢(超過了階碼表示的最大值)置溢出標志。

現(xiàn)在用一個具體的例子來說明上面的5個步驟

例題:假定X=0 .0110011*211,Y=0.1101101*2-10(此處的數(shù)均為二進制), 計算X+Y;

首先,我們要把這兩個數(shù)變成2進制表示,對于浮點數(shù)來說,階碼通常用移碼表示,而尾數(shù)通常用補碼表示。

要注意的是-10的移碼是00110
        [X]?。?0        1 010  1100110
        [Y]浮: 0        0 110  1101101
                   符號位 階碼   尾數(shù)

(1)求階差:│ΔE│=|1010-0110|=0100

(2)對階:Y的階碼小,Y的尾數(shù)右移4位
        [Y]浮變?yōu)?0 1 010 0000110 1101暫時保存

(3)尾數(shù)相加,采用雙符號位的補碼運算
     00 1100110
   +00 0000110
     00 1101100

(4)規(guī)格化:滿足規(guī)格化要求

(5)舍入處理,采用0舍1入法處理

故最終運算結(jié)果的浮點數(shù)格式為: 0 1 010 1101101

即X+Y=+0. 1101101*210

5.2 浮點數(shù)的乘除法

(1)階碼運算:階碼求和(乘法)或階碼求差(除法)
    即  [Ex+Ey]移= [Ex]移+ [Ey]補
          [Ex-Ey]移= [Ex]移+  [-Ey]補
(2)浮點數(shù)的尾數(shù)處理:浮點數(shù)中尾數(shù)乘除法運算結(jié)果要進行舍入處理

例題:X=0 .0110011*211,Y=0.1101101*2-10  求X*Y

解:[X]浮: 0 1 010 1100110
        [Y]?。?0 0 110 1101101

(1)階碼相加
[Ex+Ey]移=[Ex]移+[Ey]補=1 010+1 110=1 000
1 000為移碼表示的0

(2)原碼尾數(shù)相乘的結(jié)果為:
0 10101101101110

(3)規(guī)格化處理:已滿足規(guī)格化要求,不需左規(guī),尾數(shù)不變,階碼不變。

(4)舍入處理:按舍入規(guī)則,加1進行修正

所以 X※Y= 0.1010111*20

/******************************************************************************************
*【Author】:flyingbread
*【Date】:2007年3月2日
*【Notice】:
*1、本文為原創(chuàng)技術(shù)文章,首發(fā)博客園個人站點(http://flyingbread.cnblogs.com/),轉(zhuǎn)載和引用請注明作者及出處。
*2、本文必須全文轉(zhuǎn)載和引用,任何組織和個人未授權(quán)不能修改任何內(nèi)容,并且未授權(quán)不可用于商業(yè)。
*3、本聲明為文章一部分,轉(zhuǎn)載和引用必須包括在原文中。
*4、本文參考了網(wǎng)絡(luò)上的若干資料,不一一列舉,但是一并致謝。
******************************************************************************************/

相關(guān)文章

  • Unity實現(xiàn)卡牌翻動效果

    Unity實現(xiàn)卡牌翻動效果

    這篇文章主要為大家詳細介紹了Unity實現(xiàn)卡牌翻動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C#雙向鏈表LinkedList排序?qū)崿F(xiàn)方法

    C#雙向鏈表LinkedList排序?qū)崿F(xiàn)方法

    這篇文章主要介紹了C#雙向鏈表LinkedList排序?qū)崿F(xiàn)方法,涉及C#雙向鏈表的定義與排序技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • C#使用Npoi導(dǎo)出Excel并合并行列

    C#使用Npoi導(dǎo)出Excel并合并行列

    這篇文章主要為大家詳細介紹了C#使用Npoi導(dǎo)出Excel并合并行列,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • C#中如何分割字符串

    C#中如何分割字符串

    這篇文章主要介紹了C#中如何分割字符串問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • C# 線程同步詳解

    C# 線程同步詳解

    本文主要介紹了C#中線程同步的相關(guān)知識。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • C#中@字符d是個什么意思

    C#中@字符d是個什么意思

    這篇文章主要介紹了C#中@字符d是個什么意思?具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Unity實現(xiàn)老虎機滾動抽獎效果的示例代碼

    Unity實現(xiàn)老虎機滾動抽獎效果的示例代碼

    這篇文章主要介紹了Unity實現(xiàn)老虎機滾動抽獎效果的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • C#巧用DateTime預(yù)設(shè)可選的日期范圍(如本年度、本季度、本月等)

    C#巧用DateTime預(yù)設(shè)可選的日期范圍(如本年度、本季度、本月等)

    這篇文章主要介紹了C#巧用DateTime預(yù)設(shè)可選的日期范圍,如本年度、本季度、本月等,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Unity使用ScrollRect制作搖桿

    Unity使用ScrollRect制作搖桿

    這篇文章主要為大家詳細介紹了Unity使用ScrollRect制作搖桿,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C# 數(shù)獨求解算法的實現(xiàn)

    C# 數(shù)獨求解算法的實現(xiàn)

    這篇文章主要介紹了C# 數(shù)獨求解算法的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01

最新評論