浮点数在计算机中是如何表示的
生活随笔
收集整理的這篇文章主要介紹了
浮点数在计算机中是如何表示的
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
眾所周知,計算機中的所有數據都是以二進制表示的,浮點數也不例外。然而浮點數的二進制表示法卻不像定點數那么簡單了。
先澄清一個概念,浮點數并不一定等于小數,定點數也并不一定就是整數。所謂浮點數就是小數點在邏輯上是不固定的,而定點數只能表示小數點固定的數值,具用浮點數或定點數表示某哪一種數要看用戶賦予了這個數的意義是什么。
C++中的浮點數有6種,分別是:
float:單精度,32位
unsigned float:單精度無符號,32位
double:雙精度,64位
unsigned double:雙精度無符號,64位
long double:高雙精度,80位
unsigned long double:高雙精度無符號,80位(嚯,應該是C++中最長的內置類型了吧!)
然而不同的編譯器對它們的支持也略有不同,據我所知,很多編譯器都沒有按照IEEE規定的標準80位支持后兩種浮點數的,大多數編譯器將它們視為double,或許還有極個別的編譯器將它們視為128位?!對于128位的long double我也僅是聽說過,沒有求證,哪位高人知道這一細節煩勞告知。
下面我僅以float(帶符號,單精度,32位)類型的浮點數說明C++中的浮點數是如何在內存中表示的。先講一下基礎知識,純小數的二進制表示。(純小數就是沒有整數部分的小數,講給小學沒好好學的人)
純小數要想用二進制表示,必須先進行規格化,即化為 1.xxxxx * ( 2 ^ n ) 的形式(“^”代表乘方,2 ^ n表示2的n次方)。對于一個純小數D,求n的公式如下:
n = 1 + log2(D);// 純小數求得的n必為負數
再用 D / ( 2 ^ n ) 就可以得到規格化后的小數了。接下來就是十進制到二進制的轉化問題,為了更好的理解,先來看一下10進制的純小數是怎么表示的,假設有純小數D,它小數點后的每一位數字按順序形成一個集合:
{k1, k2, k3, ... , kn}
那么D又可以這樣表示:
D = k1 / (10 ^ 1 ) + k2 / (10 ^ 2 ) + k3 / (10 ^ 3 ) + ... + kn / (10 ^ n )
推廣到二進制中,純小數的表示法即為:
D = b1 / (2 ^ 1 ) + b2 / (2 ^ 2 ) + b3 / (2 ^ 3 ) + ... + bn / (2 ^ n )
現在問題就是怎樣求得b1, b2, b3,……,bn。算法描述起來比較復雜,還是用數字來說話吧。聲明一下,1 / ( 2 ^ n )這個數比較特殊,我稱之為位階值。
例如0.456,第1位,0.456小于位階值0.5故為0;第2位,0.456大于位階值0.25,該位為1,并將0.45減去0.25得0.206進下一位;第3位,0.206大于位階值0.125,該位為1,并將0.206減去0.125得0.081進下一位;第4位,0.081大于0.0625,為1,并將0.081減去0.0625得0.0185進下一位;第5位0.0185小于0.03125……
最后把計算得到的足夠多的1和0按位順序組合起來,就得到了一個比較精確的用二進制表示的純小數了,同時精度問題也就由此產生,許多數都是無法在有限的n內完全精確的表示出來的,我們只能利用更大的n值來更精確的表示這個數,這就是為什么在許多領域,程序員都更喜歡用double而不是float。
float的內存結構,我用一個帶位域的結構體描述如下:
struct MYFLOAT
{
bool bSign : 1; // 符號,表示正負,1位
char cExponent : 8; // 指數,8位
unsigned long ulMantissa : 23; // 尾數,23位
};
符號就不用多說了,1表示負,0表示正
指數是以2為底的,范圍是 -128 到 127,實際數據中的指數是原始指數加上127得到的,如果超過了127,則從-128開始計,其行為和X86架構的CPU處理加減法的溢出是一樣的。比如:127 + 2 = -127;127 - 2 = 127
尾數都省去了第1位的1,所以在還原時要先在第一位加上1。它可能包含整數和純小數兩部分,也可能只包含其中一部分,視數字大小而定。對于帶有整數部分的浮點數,其整數的表示法有兩種,當整數大于十進制的16777215時使用的是科學計數法,如果小于或等于則直接采用一般的二進制表示法。科學計數法和小數的表示法是一樣的。
小數部分則是直接使用科學計數法,但形式不是X * ( 10 ^ n ),而是X * ( 2 ^ n )。拆開來看。
0000000000000000000000000000000
符號位指數位尾數位
先澄清一個概念,浮點數并不一定等于小數,定點數也并不一定就是整數。所謂浮點數就是小數點在邏輯上是不固定的,而定點數只能表示小數點固定的數值,具用浮點數或定點數表示某哪一種數要看用戶賦予了這個數的意義是什么。
C++中的浮點數有6種,分別是:
float:單精度,32位
unsigned float:單精度無符號,32位
double:雙精度,64位
unsigned double:雙精度無符號,64位
long double:高雙精度,80位
unsigned long double:高雙精度無符號,80位(嚯,應該是C++中最長的內置類型了吧!)
然而不同的編譯器對它們的支持也略有不同,據我所知,很多編譯器都沒有按照IEEE規定的標準80位支持后兩種浮點數的,大多數編譯器將它們視為double,或許還有極個別的編譯器將它們視為128位?!對于128位的long double我也僅是聽說過,沒有求證,哪位高人知道這一細節煩勞告知。
下面我僅以float(帶符號,單精度,32位)類型的浮點數說明C++中的浮點數是如何在內存中表示的。先講一下基礎知識,純小數的二進制表示。(純小數就是沒有整數部分的小數,講給小學沒好好學的人)
純小數要想用二進制表示,必須先進行規格化,即化為 1.xxxxx * ( 2 ^ n ) 的形式(“^”代表乘方,2 ^ n表示2的n次方)。對于一個純小數D,求n的公式如下:
n = 1 + log2(D);// 純小數求得的n必為負數
再用 D / ( 2 ^ n ) 就可以得到規格化后的小數了。接下來就是十進制到二進制的轉化問題,為了更好的理解,先來看一下10進制的純小數是怎么表示的,假設有純小數D,它小數點后的每一位數字按順序形成一個集合:
{k1, k2, k3, ... , kn}
那么D又可以這樣表示:
D = k1 / (10 ^ 1 ) + k2 / (10 ^ 2 ) + k3 / (10 ^ 3 ) + ... + kn / (10 ^ n )
推廣到二進制中,純小數的表示法即為:
D = b1 / (2 ^ 1 ) + b2 / (2 ^ 2 ) + b3 / (2 ^ 3 ) + ... + bn / (2 ^ n )
現在問題就是怎樣求得b1, b2, b3,……,bn。算法描述起來比較復雜,還是用數字來說話吧。聲明一下,1 / ( 2 ^ n )這個數比較特殊,我稱之為位階值。
例如0.456,第1位,0.456小于位階值0.5故為0;第2位,0.456大于位階值0.25,該位為1,并將0.45減去0.25得0.206進下一位;第3位,0.206大于位階值0.125,該位為1,并將0.206減去0.125得0.081進下一位;第4位,0.081大于0.0625,為1,并將0.081減去0.0625得0.0185進下一位;第5位0.0185小于0.03125……
最后把計算得到的足夠多的1和0按位順序組合起來,就得到了一個比較精確的用二進制表示的純小數了,同時精度問題也就由此產生,許多數都是無法在有限的n內完全精確的表示出來的,我們只能利用更大的n值來更精確的表示這個數,這就是為什么在許多領域,程序員都更喜歡用double而不是float。
float的內存結構,我用一個帶位域的結構體描述如下:
struct MYFLOAT
{
bool bSign : 1; // 符號,表示正負,1位
char cExponent : 8; // 指數,8位
unsigned long ulMantissa : 23; // 尾數,23位
};
符號就不用多說了,1表示負,0表示正
指數是以2為底的,范圍是 -128 到 127,實際數據中的指數是原始指數加上127得到的,如果超過了127,則從-128開始計,其行為和X86架構的CPU處理加減法的溢出是一樣的。比如:127 + 2 = -127;127 - 2 = 127
尾數都省去了第1位的1,所以在還原時要先在第一位加上1。它可能包含整數和純小數兩部分,也可能只包含其中一部分,視數字大小而定。對于帶有整數部分的浮點數,其整數的表示法有兩種,當整數大于十進制的16777215時使用的是科學計數法,如果小于或等于則直接采用一般的二進制表示法。科學計數法和小數的表示法是一樣的。
小數部分則是直接使用科學計數法,但形式不是X * ( 10 ^ n ),而是X * ( 2 ^ n )。拆開來看。
0000000000000000000000000000000
符號位指數位尾數位
轉載于:https://www.cnblogs.com/vam/archive/2007/09/26/906535.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的浮点数在计算机中是如何表示的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: cnblog如何配置live write
- 下一篇: 开发留言本,学习笔记