單精度浮點數的取值,表示以及相關

2021-08-20 16:47:45 字數 3150 閱讀 8821

可以表示的範圍為±3.40282 * 10^38(1.1111…1×2^127)即:

0-11111110-11111111111111111111111(23個1)

單精度浮點數可以表示1.175 * 10-38(1.00…0×2^-126)的資料而不損失精度。

0-00000001-00000000000000000000001(22個0,最後一位是1)

浮點數最小能表示的是當階碼都是0時,表示2^-126*0.fractionbits

如果指數字全零,尾數字是全零,那就表示0

如果指數字全零,尾數字是非零,就表示乙個很小的數(subnormal),計算方式 (−1)^signbit × 2^−126 × 0.fractionbits(注意這裡是0.fractionbits,應該是為了和階碼是-126的時候做出區分,其實也就是比-126的時候能表示的數更小了)

如果指數字全是1,尾數字是全零,表示正負無窮

如果指數字全是1,尾數字是非零,表示不是乙個數nan

剩下的計算方式為 (−1)^signbit × 2^(exponentbits−127) × 1.fractionbits

到底什麼是補碼,一直到看了 這個知乎回答 之前,我對補碼的概念就是反碼加一,而且也沒有想過到底為什麼這樣,有什麼意義,看完之後才有些恍然大悟。

首先,第乙個問題,補碼是用來做什麼的?

補碼是用來方便alu做減法運算的,因為補碼是沒有符號的,減乙個數相當於加這個數的補碼。

所以,第二個問題就是,為什麼減乙個數相當於加乙個數的補碼呢?

在回答這個問題之前,首先問一下,如果補碼就是簡單的反碼加一為什麼要叫補碼,為什麼不直接叫反碼加一呢,這裡就要提出乙個概念,叫補數

這個例子就是補數的直觀理解,先假定表盤就表示0-11點,然後現在指標指向2點,如果我想將指標撥到3點有兩個辦法,第乙個是順時針撥1個格,第二個是逆時針撥11個格,在乙個滿刻度是12的表盤上,這兩個的效果是一樣的。抽象來講,2 - 1 = 2+11

這是為什麼呢,這就有個的概念,模,當然數學上有抽象解釋,我們這裡就可以理解成數的表示極限大小,這裡的模就是12,而對於十進位制的兩位數來說,模就是100。

繼續回到 2 - 1 = 2+11 這個問題,因為模是12,所以在這個模下,每個數有其補數,補數的意思就是模減其本身。這裡1的補數就是 12 - 1 = 11.而減去乙個數,就相當於加上這個數的補數,所以我們得到2 - 1 = 2+11。

再以十進位制兩位數為例,90 - 10 = 80.10的補數是100-10=90,所以 90 -10 = 90 + 90(忽略百位,因為這裡只有兩位)。到這裡總結一下,乙個數的補數 = 模 - 這個數,乙個數 - 另乙個數 = 乙個數 + 這個數的補數

但是如果是10 - 90 怎麼辦,難道10 - 90 = 10 + 10,-80難道等於20?沒錯!我們想用數表示-80,卻不讓加負號,那就直接讓-80 = 20。所以,乙個負數就用它絕對值的補數來表示

那麼,現在的問題是,乙個數既可以表示正數又可以表示負數,比如20既可以表示-80也可以表示20,那咋整,就規定0~99,0~49表示整數,50~99表示負數,90就代表-10這種。

對於浮點數的階碼是8位二進位制數,其表示的極限是256(11111111表示255),所以模就是256,根據上面講過的,將表示範圍一分為二:00000001~01111111表示正數,10000000~11111110表示負數(全0和全1有特殊含義)。這樣結合上面講的知識就顯而易見了,以10000000為例,256 - |x| = 128.所以表示的x=-128

雖然補碼解決了負數的問題,但是補碼還是有一定的缺陷,就是比較大小不方便,而進行浮點數運算的時候,有一步是對階,也就是比較階碼的大小然後再獲得浮點數實際大小。為了方便比較大小,浮點數使用移碼表示階碼。

移碼,顧名思義,就是當前碼通過(在座標軸上)移動之後獲得的碼,而移動的距離稱為偏置(bias)。

為什麼移動之後就方便比較大小呢,具體如下圖:

不用移碼的時候數軸是這樣的:

上面是實際的數,而下面是這些數代表的數,也就是上面講的,254代表-2之類的。

如果我們使得下面的數向右移動一格:

可以看到,現在254代表的是-3了,再移動一格呢:

依次類推,可以一直推到255代表的是最大的正數,這樣,就可以直接通過比較碼的大小來判斷實際值的大小了,是不是很方便呢

不過這裡沒有考慮全0和全1的情況,但是大概原理就是這樣了。

ps:為什麼為什麼用127做偏置而不是128:據說是為了讓數的表示範圍對稱( 原文 ),但是感覺比較牽強而且也不比用128時對稱

主要是最近在研究f16和f32的轉換才看了上面一堆東西,正題是f16和f32是怎麼轉換的。

這個就簡單了,由上面的知識可以推知,half的表示範圍最大也就到65535,而float則很大,因此當half往float轉換時,就是指數字轉換到指數字,小數字低13位補零。當然考慮到階碼是移碼,因此要-15+127才是最終的階碼。同理,從float轉換到half也是,階碼-127+15,然後砍掉小數字後13位即可。

這裡要注意,如果float原本表示的數超過了half的表示範圍,那麼轉換成的half就是階碼全是1的nan。

cite:van der zijp j. fast half float conversions[r]. working *****, 2012ftp://www. fox-toolkit.org/pub/fasthalffloatconversion. pdf, 2008.

單精度浮點數(IEEE754)

單精度浮點數佔據4個位元組,4個位元組的分配如下 a 第一位為符號位,0表示正,1表示負 b 第2 9位為階碼,採用移碼表示 c 第10 32位為尾數,採用原碼表示。1 給定32位串,如何轉換成十進位制數 假設記憶體中存在32位串 cd cc 08 41。因為intel cpu採用little en...

半精度浮點數到單精度的python 實現

實現原理可參考3.參考文獻部分。輸入引數s是字串形式的16位二進數,如 0011010101010101 def halfpre2spre s s代表16位二進數,sign int s 0 res0 pow 1 sign 符號位 exp int 0b s 1 6 2 指數字 endpre s 6 尾...

js 單精度浮點數轉10進製 浮點數轉換為十進位制數

題目 將32位浮點數 01000010111011010000000000000000 轉換為十進位制格式 根據國際標準ieee 754,任意乙個二進位制浮點數v可以表示成下面的形式 1 1 s表示符號位,當s 0,v為正數 當s 1,v為負數。2 m表示有效數字,大於等於1,小於2。3 2 e表示...