帶有小數點的10進製數轉換成2進製

2021-06-10 11:41:01 字數 3459 閱讀 4220

原文:

從儲存結構和演算法上來講,double和float是一樣的,不一樣的地方僅僅是float是32位的,double是64位的,所以double能儲存更高的精度。

任何資料在記憶體中都是以二進位制(0或1)順序儲存的,每乙個1或0被稱為1位,而在x86cpu上乙個位元組是8位。比如乙個16位(2位元組)的short int型變數的值是1000,那麼它的二進位制表達就是:00000011 11101000。由於intel cpu的架構原因,它是按位元組倒序儲存的,那麼就因該是這樣:11101000 00000011,這就是定點數1000在記憶體中的結構。

目前c/c++編譯器標準都遵照ieee制定的浮點數表示法來進行float,double運算。這種結構是一種科學計數法,用符號、指數和尾數來表示,底數定為2——即把乙個浮點數表示為尾數乘以2的指數次方再添上符號。下面是具體的規格:

````````符號位 階碼 尾數 長度

float 1 8 23 32

double 1 11 52 64

臨時數 1 15 64 80

由於通常c編譯器預設浮點數是double型的,下面以double為例:

共計64位,折合8位元組。由最高到最低位分別是第63、62、61、……、0位:

最高位63位是符號位,1表示該數為負,0正;

62-52位,一共11位是指數字;

51-0位,一共52位是尾數字。

按照ieee浮點數表示法,下面將把double型浮點數38414.4轉換為十六進製制**。

把整數部和小數部分開處理:整數部直接化十六進製制:960e。小數的處理:

0.4=0.5*0+0.25*1+0.125*1+0.0625*0+……

實際上這永遠算不完!這就是著名的浮點數精度問題。所以直到加上前面的整數部分算夠53位就行了(隱藏位技術:最高位的1不寫入記憶體)。

如果你夠耐心,手工算到53位那麼因該是:38414.4(10)=1001011000001110.0110101010101010101010101010101010101(2)

科學記數法為:1.001……乘以2的15次方。指數為15!

於是來看階碼,一共11位,可以表示範圍是-1024 ~ 1023。因為指數可以為負,為了便於計算,規定都先加上1023,在這裡,15+1023=1038。二進位制表示為:100 00001110

符號位:正—— 0 !

合在一起(尾數二進位制最高位的1不要):

01000000 11100010 11000001 11001101 01010101 01010101 01010101 01010101

按位元組倒序儲存的十六進製制數就是:

55 55 55 55 cd c1 e2 40

找點資料看看就明白了:

任何資料在記憶體中都是以二進位制(1或著0)順序儲存的,每乙個1或著0被稱為1位,而在x86cpu上乙個位元組是8位。比如

乙個16位(2位元組)的short int型變數的值是1156,那麼它的二進位制表達就是:00000100 10000100。由於intel cpu的

00000100,這就是定點數1156在記憶體中的結構。

那麼浮點數是如何儲存的呢?目前已知的所有的c/c++編譯器都是按照ieee(國際電子電器工程師協會)制定的ieee 浮

點數表示法來進行運算的。這種結構是一種科學表示法,用符號(正或負)、指數和尾數來表示,底數被確定為2,也

就是說是把乙個浮點數表示為尾數乘以2的指數次方再加上符號。下面來看一下具體的float的規格:

float

共計32位,折合4位元組

由最高到最低位分別是第31、30、29、……、0位

31位是符號位,1表示該數為負,0反之。

30-23位,一共8位是指數字。

22-0位,一共23位是尾數字。

每8位分為一組,分成4組,分別是a組、b組、c組、d組。

每一組是乙個位元組,在記憶體中逆序儲存,即:dcba

我們先不考慮逆序儲存的問題,因為那樣會把讀者徹底搞暈,所以我先按照順序的來講,最後再把他們翻過來就行了。

現在讓我們按照ieee浮點數表示法,一步步的將float型浮點數12345.0f轉換為十六進製制**。在處理這種不帶小數的

浮點數時,直接將整數部轉化為二進位制表示:1 11100010 01000000也可以這樣表示:11110001001000000.0然後將小數

點向左移,一直移到離最高位只有1位,就是最高位的1:1.11100010010000000一共移動了16位,在布耳運算中小數點

每向左移一位就等於在以2為底的科學計算法表示中指數+1,所以原數就等於這樣:1.11100010010000000 * ( 2 ^ 16 

)好了,現在我們要的尾數和指數都出來了。顯而易見,最高位永遠是1,因為你不可能把買了16個雞蛋說成是買了0016

個雞蛋吧?(呵呵,可別拿你買的臭雞蛋甩我~),所以這個1我們還有必要保留他嗎?(眾:沒有!)好的,我們刪掉

他。這樣尾數的二進位制就變成了:11100010010000000最後在尾數的後面補0,一直到補夠23位:

11100010010000000000000(md,這些個0差點沒把我數的背過氣去~)

再回來看指數,一共8位,可以表示範圍是0 - 255的無符號整數,也可以表示-128 - 127的有符號整數。但因為指數是

可以為負的,所以為了統一把十進位制的整數化為二進位制時,都先加上127,在這裡,我們的16加上127後就變成了143,

二進位制表示為:10001111

12345.0f這個數是正的,所以符號位是0,那麼我們按照前面講的格式把它拼起來:

0 10001111 11100010010000000000000

01000111 11110001 00100000 00000000

再轉化為16進製為:47 f1 20 00,最後把它翻過來,就成了:00 20 f1 47。

現在你自己把54321.0f轉為二進位制表示,自己動手練一下!

有了上面的基礎後,下面我再舉乙個帶小數的例子來看一下為什麼會出現精度問題。

按照ieee浮點數表示法,將float型浮點數123.456f轉換為十六進製制**。對於這種帶小數的就需要把整數部和小數部

分開處理。整數部直接化二進位制:100100011。小數部的處理比較麻煩一些,也不太好講,可能反著講效果好一點,比

如有乙個十進位制純小數0.57826,那麼5是十分位,位階是1/10;7是百分位,位階是1/100;8是千分位,位階是1/1000

……,這些位階分母的關係是10^1、10^2、10^3……,現假設每一位的序列是,在這裡就是5

、7、8、2、6,而這個純小數就可以這樣表示:n = s1 * ( 1 / ( 10 ^ 1 ) ) + s2 * ( 1 / ( 10 ^ 2 ) ) + s3 * ( 1 / ( 10 ^ 3 ) ) + …… + sn * ( 1 / ( 10 ^ n ) )。把這個公式推廣到b進製純小數中就是這樣:

n = s1 * ( 1 / ( b ^ 1 ) ) + s2 * ( 1 / ( b ^ 2 ) ) + s3 * ( 1 / ( b ^ 3 ) ) + …… + sn * ( 1 / ( b ^ n ) )

10進製數轉換成2進製數

2.十進位制轉換成二進位制 演算法 利用while語句 當所輸入的數不為1時,執行while迴圈 在while迴圈中將輸入的數插入順序棧中 只支援整形資料 include using namespace std const int stacksize 10 class seqstack seqsta...

將10進製數轉換成任意進製數

要想解決這個問題我們先來看看10進製轉2進製的 includemain for i j 1 i 0 i 將陣列逆序輸出 printf d a i printf n 我們再來看看10進製轉16進製制的 include main char b 16 scanf d n while n for i j 1...

10進製數轉換成16進製制

十六進製制的元素個數固定,而且還有對應編號,可以用查表法.乙個int型別十進位制數在32位作業系統中佔4個位元組,32位2進製數取它的低8位,例如60,在記憶體中以二進位制數0011 1100存放,而乙個十六進製制數中每一位數對應二進位制中4位數,因此可以將十進位制數與f進行 與 運算,得出低四位 ...