2.1 信息存儲(chǔ)
1字節(jié)(byte)= 8位(bit)
2.1.1 十六進(jìn)制表示法
十六進(jìn)制(簡(jiǎn)寫(xiě)為"hex")使用數(shù)字 '0' ~ '9' 以及字符 'A' ~ 'F' 來(lái)表示芽偏。
1 個(gè)十六進(jìn)制數(shù)表示 4 個(gè)二進(jìn)制數(shù)航棱。
當(dāng) x=2n 時(shí)回懦,很容易將 x 寫(xiě)成十六進(jìn)制形式端辱,x 的二進(jìn)制表示就是 1 后面跟 n 個(gè) 0 。十六進(jìn)制數(shù)字 0 代表 4 個(gè)二進(jìn)制 0。所以想罕,當(dāng) n 表示成 i+4j 的形式疚漆,其中 0 ≦ i ≦ 3,x 開(kāi)頭十六進(jìn)制為1(i=0)僵腺、2(i=1)、4(i=2)、8(i=3)矾芙,后面跟隨 j 個(gè)十六進(jìn)制的 0。
2.1.2 字?jǐn)?shù)據(jù)大小
C聲明 | C聲明 | 字節(jié)數(shù) | 字節(jié)數(shù) |
---|---|---|---|
有符號(hào) | 無(wú)符號(hào) | 32位 | 64位 |
[signed] char | unsigned char | 1 | 1 |
short | unsigned short | 2 | 2 |
int | unsigned | 4 | 4 |
long | unsigned long | 4 | 8 |
int32_t | uint32_t | 4 | 4 |
int64_t | uint64_t | 8 | 8 |
char * | 4 | 8 | |
float | 4 | 4 | |
double | 8 | 8 |
2.1.3 尋址和字節(jié)順序
最低有效字節(jié)在最前面的方式近上,為小端法(little endian)剔宪。
最高有效字節(jié)在最前面的方式,為大端法(big endian)——與書(shū)寫(xiě)習(xí)慣一致壹无。
假設(shè)變量 x 的類(lèi)型為 int葱绒,位于地址 0x100 處,它的十六進(jìn)制值為 0x01234567斗锭。地址范圍 0x100?0x103 的字節(jié)順序依賴于機(jī)器的類(lèi)型:
注意地淀,在字 0x01234567 中,高位字節(jié)的十六進(jìn)制值為 0x01岖是,而低位字節(jié)值為 0x67帮毁。
// 判斷大小端
int is_little_endian(void) {
int i = 0xff;
unsigned char *p = &i;
return p[0] == 0xff;
}
2.1.4 表示字符串
C語(yǔ)言中字符串被編碼為一個(gè)以null(其值為0)字符結(jié)尾的字符數(shù)組。
字母 'a' ~ 'z' 的 ASCII 碼為 0x61 ~ 0x7A豺撑。
2.1.5 表示代碼
不同的機(jī)器類(lèi)型使用不同的且不兼容的指令和編碼方式烈疚。
2.1.6 布爾代數(shù)簡(jiǎn)介
1 為 true(真)
0 為 false(假)
圖2-7↓ 布爾代數(shù)的運(yùn)算。二進(jìn)制值 1 和 0 表示邏輯值 TRUE 或者 FALSE 聪轿,而運(yùn)算符 ?爷肝、&、丨和 ^ 分別表示邏輯運(yùn)算 NOT屹电、 AND阶剑、OR 和 EXCLUSIVE-OR
可以將上述 4 個(gè)布爾運(yùn)算擴(kuò)展到位向量的運(yùn)算,位向量就是固定長(zhǎng)度為 W 危号、由 0 和 1 組成的串牧愁。位向量的運(yùn)算可以定義成參數(shù)的每個(gè)對(duì)應(yīng)元素之間的運(yùn)算。
舉個(gè)例子外莲,假設(shè) w=4 猪半,參數(shù) a = [0110] 兔朦,b=[1100]。那么 4 種運(yùn)算a&b磨确、a|b沽甥、a^b 和?b 分別得到以下結(jié)果:
關(guān)于布爾代數(shù)和布爾環(huán)的更多內(nèi)容
布爾運(yùn)算 & 對(duì) | 的分配律,寫(xiě)為 a & (b | c) = (a & b) | (a & c)乏奥。
布爾運(yùn)算 | 對(duì) & 的分配律摆舟,寫(xiě)為 a | (b & c) = (a | b) & (a | c)。
對(duì)于任何值 a 來(lái)說(shuō)邓了,a ^ a = 0恨诱。
(a ^ b) ^ a = b。
2.1.7 C語(yǔ)言中的位級(jí)運(yùn)算
C的表達(dá)式 | 二進(jìn)制表達(dá)式 | 二進(jìn)制結(jié)果 | 十六進(jìn)制結(jié)果 |
---|---|---|---|
~0x41 | ~[0100 0001] | [1011 1110] | 0xBE |
~0x00 | ~[0000 0000] | [1111 1111] | 0xFF |
0x69&0x55 | [0110 1001]&[0101 0101] | [0100 0001] | 0x41 |
0x69|0x55 | [0110 1001]|[0101 0101] | [0111 1101] | 0x7D |
位級(jí)運(yùn)算的一個(gè)常見(jiàn)用法就是實(shí)現(xiàn)掩碼運(yùn)算骗炉,這里掩碼是一個(gè)為模式照宝,表示從一個(gè)字中選出的位的集合。
如:x = 0x89ABCDEF句葵,x&0xFF = 0x000000EF
表達(dá)式 ~0 將生成一個(gè)全 1 的掩碼厕鹃,不管機(jī)器的字大小是多少。
2.1.8 C語(yǔ)言中的邏輯運(yùn)算
|| OR 或
&& AND 與
! NOT 非
表達(dá)式 | 結(jié)果 |
---|---|
!0x41 | 0x00 |
!0x00 | 0x01 |
!!0x41 | 0x01 |
0x69&&0x55 | 0x01 |
0x69||0x55 | 0x01 |
如果對(duì)第一個(gè)參數(shù)求值就能確定表達(dá)式的結(jié)果乍丈,那么邏輯運(yùn)算符就不會(huì)對(duì)第二個(gè)參數(shù)求值剂碴。
2.1.9 C語(yǔ)言中的位移運(yùn)算
左移:x<<k,x向左移動(dòng)k位诗赌,丟棄最高的k位汗茄,并在右端補(bǔ)k個(gè)0。移位量應(yīng)該是一個(gè)0~w-1之間的值铭若。
邏輯右移:x>>k洪碳,在左端補(bǔ)k個(gè)0。
算術(shù)右移:x>>k叼屠,在左端補(bǔ)k個(gè)最高有效位的值瞳腌。
2.2 整數(shù)表示
數(shù)學(xué)術(shù)語(yǔ)
下標(biāo)w表示數(shù)據(jù)表示中的位數(shù)
符號(hào) | 類(lèi)型 | 含義 |
---|---|---|
函數(shù) | 二進(jìn)制轉(zhuǎn)補(bǔ)碼 | |
函數(shù) | 二進(jìn)制轉(zhuǎn)無(wú)符號(hào)數(shù) | |
函數(shù) | 無(wú)符號(hào)數(shù)轉(zhuǎn)二進(jìn)制 | |
函數(shù) | 無(wú)符號(hào)轉(zhuǎn)補(bǔ)碼 | |
函數(shù) | 補(bǔ)碼轉(zhuǎn)二進(jìn)制 | |
函數(shù) | 補(bǔ)碼轉(zhuǎn)無(wú)符號(hào)數(shù) | |
常數(shù) | 最小補(bǔ)碼值 | |
常數(shù) | 最大補(bǔ)碼值 | |
常數(shù) | 最大無(wú)符號(hào)數(shù) | |
操作 | 補(bǔ)碼加法 | |
操作 | 無(wú)符號(hào)數(shù)加法 | |
操作 | 補(bǔ)碼乘法 | |
操作 | 無(wú)符號(hào)數(shù)乘法 | |
操作 | 補(bǔ)碼取反 | |
操作 | 無(wú)符號(hào)數(shù)取反 |
2.2.1 整型數(shù)據(jù)類(lèi)型
32位程序上C語(yǔ)言整型數(shù)據(jù)類(lèi)型的典型取值范圍
C數(shù)據(jù)類(lèi)型 | 最小值 | 最大值 |
---|---|---|
[signed]char | -128 | 127 |
unsigned char | 0 | 255 |
short | -32 768 | 32 767 |
unsigned short | 0 | 65 535 |
int | -2 147 483 648 | 2 147 483 647 |
unsigned | 0 | 4 294 967 295 |
long | -2 147 483 648 | 2 147 483 647 |
unsigned long | 0 | 4 294 967 295 |
int32_t | -2 147 483 648 | 2 147 483 647 |
uint32_t | 0 | 4 294 967 295 |
int64_t | -9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
uint_64_t | 0 | 18 446 744 073 709 551 615 |
64位程序上C語(yǔ)言整型數(shù)據(jù)類(lèi)型的典型取值范圍
C數(shù)據(jù)類(lèi)型 | 最小值 | 最大值 |
---|---|---|
[signed]char | -128 | 127 |
unsigned char | 0 | 255 |
short | -32 768 | 32 767 |
unsigned short | 0 | 65 535 |
int | -2 147 483 648 | 2 147 483 647 |
unsigned | 0 | 4 294 967 295 |
long | -9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
unsigned long | 0 | 18 446 744 073 709 551 615 |
int32_t | -2 147 483 648 | 2 147 483 647 |
uint32_t | 0 | 4 294 967 295 |
int64_t | -9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
uint_64_t | 0 | 18 446 744 073 709 551 615 |
C語(yǔ)言的整型數(shù)據(jù)類(lèi)型的保證的取值范圍
C數(shù)據(jù)類(lèi)型 | 最小值 | 最大值 |
---|---|---|
[signed]char | -127 | 127 |
unsigned char | 0 | 255 |
short | -32 767 | 32 767 |
unsigned short | 0 | 65 535 |
int | -32 767 | 32 767 |
unsigned | 0 | 65 535 |
long | -2 147 483 647 | 2 147 483 647 |
unsigned long | 0 | 4 294 967 295 |
int32_t | -2 147 483 648 | 2 147 483 647 |
uint32_t | 0 | 4 294 967 295 |
int64_t | -9 223 372 036 854 775 808 | 9 223 372 036 854 775 807 |
uint_64_t | 0 | 18 446 744 073 709 551 615 |
2.2.2 無(wú)符號(hào)數(shù)的編碼
無(wú)符號(hào)數(shù)編碼的定義
對(duì)向量
最大值是用位向量[11...1]表示
以4位情況為例,
2.2.3 補(bǔ)碼編碼
補(bǔ)碼編碼的定義
對(duì)向量
最小值是用位向量[10...0]表示
(也就是設(shè)置這個(gè)位為負(fù)權(quán)镜雨,但是清除其他所有的位)
以4位情況為例嫂侍,
最大值是用位向量[01...1]表示
(清除具有負(fù)權(quán)的位,而設(shè)置其他所有的位)
以4位情況為例荚坞,
注意:
1挑宠、補(bǔ)碼的范圍是不對(duì)稱的:|TMin| = |TMax| + 1 ,也就是說(shuō)颓影,TMin沒(méi)有與之對(duì)應(yīng)的正數(shù)各淀。
2、最大的無(wú)符號(hào)數(shù)值剛好比補(bǔ)碼的最大值的兩倍大一點(diǎn):
3诡挂、-1 和 UMax 有同樣的位表示——一個(gè)全 1 的串碎浇,數(shù)值 0 在兩種表示方式中都是全 0 的串临谱。
2.2.4 有符號(hào)數(shù)和無(wú)符號(hào)數(shù)之間的轉(zhuǎn)換
補(bǔ)碼轉(zhuǎn)換為無(wú)符號(hào)數(shù)
對(duì)滿足 的
有:
比如,奴璃,同時(shí)
推導(dǎo):補(bǔ)碼轉(zhuǎn)換為無(wú)符號(hào)數(shù)
根據(jù)上個(gè)公式的兩種情況悉默,在的補(bǔ)碼表示中,位
決定了
是否為負(fù)苟穆。
無(wú)符號(hào)數(shù)轉(zhuǎn)換為補(bǔ)碼
對(duì)滿足的
有:
推導(dǎo):無(wú)符號(hào)數(shù)轉(zhuǎn)換為補(bǔ)碼
在u的無(wú)符號(hào)表示中抄课,對(duì)上個(gè)公式的兩種情況來(lái)說(shuō),位決定了 u 是否大于
2.2.5 C語(yǔ)言中的有符號(hào)數(shù)與無(wú)符號(hào)數(shù)
C語(yǔ)言支持所有整型數(shù)據(jù)類(lèi)型的有符號(hào)和無(wú)符號(hào)運(yùn)算雳旅。盡管C語(yǔ)言標(biāo)準(zhǔn)沒(méi)有指定有符號(hào)數(shù)要采用某種表示,但是幾乎所有機(jī)器都使用補(bǔ)碼岭辣。通常,大多數(shù)數(shù)字都默認(rèn)為是有符號(hào)的甸饱。要?jiǎng)?chuàng)建一個(gè)無(wú)符號(hào)常量沦童,必須加上后綴字符 'U' 或者 'u' 。
C語(yǔ)言無(wú)符號(hào)數(shù)和有符號(hào)數(shù)之間的轉(zhuǎn)換叹话,一般原則是底層的位表示保持不變偷遗。
當(dāng)執(zhí)行一個(gè)運(yùn)算時(shí),如果它的一個(gè)運(yùn)算數(shù)是有符號(hào)的而另一個(gè)是無(wú)符號(hào)的驼壶,那么C語(yǔ)言會(huì)隱式地將有符號(hào)參數(shù)強(qiáng)制類(lèi)型轉(zhuǎn)換為無(wú)符號(hào)數(shù)氏豌,并假設(shè)這兩個(gè)數(shù)都是非負(fù)的,來(lái)執(zhí)行這個(gè)運(yùn)算热凹。
C語(yǔ)言中TMin的寫(xiě)法
定義在頭文件 limits.h 中
#define INT_MAX 2147483647
#define INT_MIN (-INT_MAX - 1)
2.2.6 擴(kuò)展一個(gè)數(shù)字的位表示
要將一個(gè)無(wú)符號(hào)數(shù)轉(zhuǎn)換為一個(gè)更大的數(shù)據(jù)類(lèi)型泵喘,在開(kāi)頭添加0,這種運(yùn)算被稱為零擴(kuò)展(zero extension)般妙。
要將一個(gè)補(bǔ)碼數(shù)字轉(zhuǎn)換為一個(gè)更大的數(shù)據(jù)類(lèi)型纪铺,可以執(zhí)行一個(gè)符號(hào)擴(kuò)展(sign extension),在表示中添加最高有效位的值碟渺。
2.2.7 截?cái)鄶?shù)字
無(wú)符號(hào)數(shù)的截?cái)嘟Y(jié)果是:
補(bǔ)碼數(shù)字的截?cái)嘟Y(jié)果是:
2.2.8 關(guān)于有符號(hào)數(shù)與無(wú)符號(hào)數(shù)的建議
有符號(hào)數(shù)到無(wú)符號(hào)數(shù)的隱式轉(zhuǎn)換鲜锚,是會(huì)導(dǎo)致錯(cuò)誤或者漏洞的方式,避免這類(lèi)錯(cuò)誤的一種方法就是絕不使用無(wú)符號(hào)數(shù)苫拍。
2.3 整數(shù)運(yùn)算
2.3.1 無(wú)符號(hào)加法
將操作
描述為無(wú)符號(hào)數(shù)加法
對(duì)滿足的
和
有:
檢測(cè)無(wú)符號(hào)數(shù)加法中的溢出
對(duì)在范圍 中的
和
绒极,令
骏令。則對(duì)計(jì)算
,當(dāng)且僅當(dāng)
(或者等價(jià)地
)時(shí),發(fā)生了溢出集峦。
阿貝爾群
每個(gè)元素有一個(gè)加法逆元伏社】俅蹋考慮 w 位的無(wú)符號(hào)數(shù)的集合,執(zhí)行加法運(yùn)算摘昌。對(duì)于每個(gè)值 x速妖,必然有某個(gè)值
滿足
。
無(wú)符號(hào)數(shù)求反
對(duì)滿足 的任意
聪黎,其
位的無(wú)符號(hào)逆元
由下式給出:
2.3.2 補(bǔ)碼加法
對(duì)滿足 之內(nèi)的整數(shù)
和
罕容,有:
兩個(gè)數(shù)的 位補(bǔ)碼之和有完全相同的位級(jí)表示。我們可以按如下步驟表示運(yùn)算
:將其參數(shù)轉(zhuǎn)換為無(wú)符號(hào)數(shù)稿饰,執(zhí)行無(wú)符號(hào)數(shù)加法锦秒,再將結(jié)果轉(zhuǎn)換為補(bǔ)碼:
檢測(cè)補(bǔ)碼加法中的溢出
對(duì)滿足 的
和
喉镰,令
旅择。當(dāng)且僅當(dāng)
侣姆,但
時(shí)生真,計(jì)算
發(fā)生了正溢出。當(dāng)且僅當(dāng)
柱蟀,但
時(shí),計(jì)算
發(fā)生了負(fù)溢出蚜厉。
2.3.3 補(bǔ)碼的非
可以看到范圍在 中的每個(gè)數(shù)字
都有
下的加法逆元长已,我們將
表示如下:
對(duì)滿足 的
,其補(bǔ)碼的非
由下式給出
也就是說(shuō)昼牛,對(duì) 位的補(bǔ)碼加法來(lái)說(shuō)术瓮,
是自己的加法的逆,而對(duì)其他任何數(shù)值
都有
作為其加法的逆贰健。
補(bǔ)碼非的位級(jí)表示
計(jì)算一個(gè)位級(jí)表示的值的補(bǔ)碼非有幾種聰明的方法斤斧。
1、執(zhí)行位級(jí)補(bǔ)碼非的第一種方法是對(duì)每一位求補(bǔ)霎烙,再對(duì)結(jié)果加1撬讽。在C語(yǔ)言中,我們可以說(shuō)悬垃,對(duì)于任意整數(shù)值 x 游昼,計(jì)算表達(dá)式 -x 和 ~x+1 得到的結(jié)果完全一樣。
2尝蠕、計(jì)算一個(gè)數(shù) x 的補(bǔ)碼非的第二種方法是建立在將位向量分為兩部分的基礎(chǔ)之上的烘豌。假設(shè) 是最右邊的 1 的位置,因而
的位級(jí)表示形如
看彼。(只要
就能夠找到這樣的
廊佩。)這個(gè)值的非寫(xiě)成二進(jìn)制格式就是
囚聚。也就是,我們對(duì)位
左邊的所有位取反标锄。
2.3.4 無(wú)符號(hào)乘法
對(duì)滿足 的
和
有:
2.3.5 補(bǔ)碼乘法
對(duì)滿足 的
和
有:
對(duì)于無(wú)符號(hào)和補(bǔ)碼乘法來(lái)說(shuō)顽铸,乘法運(yùn)算的位級(jí)表示都是一樣的。
2.3.6 乘以常數(shù)
乘以 2 的冪
設(shè) 為位模式
表示的無(wú)符號(hào)整數(shù)料皇。那么谓松,對(duì)于任何
,我們都認(rèn)為
給出了
的
位的無(wú)符號(hào)表示践剂,這里右邊增加了
個(gè) 0 鬼譬。
與 2 的冪相乘的無(wú)符號(hào)乘法
C 變量 x 和 k 有無(wú)符號(hào)數(shù)值 和
,且
逊脯,則 C 表達(dá)式 x<<k 產(chǎn)生數(shù)值
优质。
與 2 的冪相乘的補(bǔ)碼乘法
C 變量 x 和 k 有補(bǔ)碼值 和 無(wú)符號(hào)數(shù)值
,且
军洼,則 C 表達(dá)式 x<<k 產(chǎn)生數(shù)值
盆赤。
由于整數(shù)乘法比移位和加法的代價(jià)要大得多,許多 C 語(yǔ)言編譯器試圖以移位歉眷、加法和減法的組合來(lái)消除很多整數(shù)乘以常數(shù)的情況。
對(duì)于某個(gè)常數(shù) K 的表達(dá)式 x * K 生成代碼颤枪。編譯器會(huì)將 K 的二進(jìn)制表示表達(dá)為一組 0 和 1 交替的序列:
考慮一組從位位置 n 到位位置 m 的連續(xù)的 1(nm)汗捡。我們可以用下面兩種不同形式中的一種來(lái)計(jì)算這些位對(duì)乘積的影響:
形式A:(x<<n)+(x<<(n-1)+...+(x<<m)
形式B:(x<<(n+1))-(x<<m)
把每個(gè)這樣連續(xù)的 1 的結(jié)果加起來(lái),不用做任何乘法畏纲,我們就能計(jì)算出 x * K 扇住。
2.3.7 除以 2 的冪
整數(shù)除法要比整數(shù)乘法更慢。除以 2 的冪也可以用移位運(yùn)算來(lái)實(shí)現(xiàn)盗胀。無(wú)符號(hào)和補(bǔ)碼數(shù)分別使用邏輯移位和算術(shù)移位來(lái)達(dá)到目的艘蹋。
整數(shù)除法總是舍入到零。它將向下
舍入一個(gè)正值票灰,而
向上
舍入一個(gè)負(fù)值女阀。
除以 2 的冪的無(wú)符號(hào)除法
C 變量 x 和 k 有無(wú)符號(hào)數(shù)值 和
,且
屑迂,則 C 表達(dá)式 x >> k 產(chǎn)生數(shù)值
浸策。
除以 2 的冪的補(bǔ)碼除法,向下舍入
C 變量 x 和 k 有補(bǔ)碼值 和 無(wú)符號(hào)數(shù)值
惹盼,且
庸汗,則當(dāng)執(zhí)行算術(shù)位移時(shí), C 表達(dá)式 x >> k 產(chǎn)生數(shù)值
手报。
對(duì)于負(fù)數(shù)來(lái)說(shuō)蚯舱,向下舍入結(jié)果會(huì)有偏差改化。
除以 2 的冪的補(bǔ)碼除法,向上舍入
C 變量 x 和 k 有補(bǔ)碼值 和 無(wú)符號(hào)數(shù)值
枉昏,且
陈肛,則當(dāng)執(zhí)行算術(shù)位移時(shí), C 表達(dá)式 (x+(1<<k)-1) >> k 產(chǎn)生數(shù)值
凶掰。
2.3.8 關(guān)于整數(shù)運(yùn)算的最后思考
- 計(jì)算機(jī)執(zhí)行的“整數(shù)”運(yùn)算實(shí)際上是一種模運(yùn)算形式燥爷。
- 表示數(shù)字的有限字長(zhǎng)限制了可能的值的取值范圍,結(jié)果運(yùn)算可能溢出懦窘。
- 補(bǔ)碼表示提供了一種既能表示負(fù)數(shù)也能表示正數(shù)的靈活方法前翎,同時(shí)使用了與執(zhí)行無(wú)符號(hào)算術(shù)相同的位級(jí)實(shí)現(xiàn)。
- 無(wú)論運(yùn)算數(shù)是以無(wú)符號(hào)形式還是以補(bǔ)碼形式表示的畅涂,都有完全一樣或者類(lèi)似的位級(jí)行為港华。
2.4 浮點(diǎn)數(shù)
浮點(diǎn)表示對(duì)形如 的有理數(shù)進(jìn)行編碼。它對(duì)執(zhí)行涉及非常大的數(shù)字(|V|>>0)午衰、非常接近于0(|V|<<1)的數(shù)字立宜,以及更普遍地作為實(shí)數(shù)運(yùn)算的近似值的計(jì)算,是很有用的臊岸。
2.4.1 二進(jìn)制小數(shù)
形如 的表示法橙数,其中每個(gè)二進(jìn)制數(shù)字滥朱,或者稱為位衡招,
的取值范圍是 0 和 1 ,這種表示方法表示的數(shù) b 定義如下:
點(diǎn)左邊的位的權(quán)是 2 的正冪擎椰,點(diǎn)右邊的位的權(quán)是 2 的負(fù)冪逻住。
例如钟哥, 表示數(shù)字
=
形如 的數(shù)表示的是剛好小于 1 的數(shù)。例如瞎访,
表示
腻贰,我們將用簡(jiǎn)單的表達(dá)法
來(lái)表示這樣的數(shù)值。
定點(diǎn)表示法不能很有效的表示非常大的數(shù)字扒秸。
2.4.2 IEEE 浮點(diǎn)表示
IEEE浮點(diǎn)標(biāo)準(zhǔn)用 的形式來(lái)表示一個(gè)數(shù):
- 符號(hào)(sign)
決定這數(shù)是負(fù)數(shù)(
)還是正數(shù)(
)播演,而對(duì)于數(shù)值
的符號(hào)位解釋作為特殊情況處理。
- 尾數(shù)(significand)
是一個(gè)二進(jìn)制小數(shù)伴奥,它的范圍是
宾巍,或者是
。
- 階碼(exponent)
的作用是對(duì)浮點(diǎn)數(shù)加權(quán)渔伯,這個(gè)權(quán)重是
的
次冪(可能是負(fù)數(shù))顶霞。
將浮點(diǎn)數(shù)的位表示劃分為三個(gè)字段,分別對(duì)這些值進(jìn)行編碼:
- 一個(gè)單獨(dú)的符號(hào)位
直接編碼符號(hào)
。
-
位的階碼字段
編碼階碼
选浑。
-
位小數(shù)字段
編碼尾數(shù)
蓝厌,但是編碼出來(lái)的值也依賴于階碼字段的值是否等于 0 。
在單精度浮點(diǎn)格式(C 語(yǔ)言中的 float)中古徒,s拓提、exp 和 frac 字段分別為 位、
位和
位隧膘,得到一個(gè) 32 位的表示代态。
在雙精度浮點(diǎn)格式(C 語(yǔ)言中的 double)中,s疹吃、exp 和 frac 字段分別為 位蹦疑、
位和
位,得到一個(gè) 64 位的表示萨驶。
給定位表示歉摧,根據(jù) exp 的值,被編碼的值可以分成三種不同的情況(最后一種情況有兩個(gè)變種)腔呜。圖 2-33 說(shuō)明了對(duì)單精度格式的情況叁温。
情況1:規(guī)格化的值
當(dāng) exp 階碼域的位模式既不全為 0,也不全為 1 時(shí)核畴。
階碼字段被解釋為以偏置(biased)形式表示的有符號(hào)整數(shù)膝但。階碼的值是 ,其中 e 是無(wú)符號(hào)數(shù)谤草,Bias 是一個(gè)等于 (單精度是127跟束,雙精度是1023)的偏置值。
小數(shù)字段 frac 被解釋為描述小數(shù)值 咖刃,其中 ,其二進(jìn)制表示為 憾筏,也就是二進(jìn)制小數(shù)點(diǎn)在最高有效位的左邊嚎杨。
尾數(shù)定義為 。這種方式叫做隱含的以 1 開(kāi)頭的(implied leading 1)表示氧腰,因?yàn)榭梢园? 看成一個(gè)二進(jìn)制表達(dá)式為 的數(shù)字枫浙。
情況2:非規(guī)格化的值
當(dāng) exp 階碼域?yàn)槿?0 時(shí),所表示的數(shù)是非規(guī)格化形式古拴。
階碼值是
尾數(shù)的值是 箩帚,也就是小數(shù)字段的值,不包含隱含的開(kāi)頭的1黄痪。
非規(guī)格化數(shù)有兩個(gè)用途:
1.提供了一種表示數(shù)值 0 的方法紧帕。
2.表示那些非常接近于 0.0 的數(shù)。
情況3:特殊值
當(dāng) exp 階碼域全為 1時(shí),表示特殊值是嗜。
當(dāng)小數(shù)域全為 0 時(shí)愈案,得到的值表示無(wú)窮。當(dāng) s=0 時(shí)是 鹅搪,或者當(dāng) s=1 時(shí)是
站绪。
當(dāng)小數(shù)域?yàn)榉橇銜r(shí),結(jié)果值被稱為 “NaN”丽柿,即“不是一個(gè)數(shù)(Not a Number)”的縮寫(xiě)恢准。
2.4.3 數(shù)字示例
圖 2-35 展示了假定的 8 位浮點(diǎn)格式的示例,其中有 的階碼位和
的小數(shù)位甫题。偏置量是
馁筐。
可以觀察到最大非規(guī)格化數(shù) 和最小規(guī)格化數(shù) 之間的平滑轉(zhuǎn)變。這種平滑性歸功于我們對(duì)非規(guī)格化數(shù)的 E 的定義幔睬。通過(guò)將 E 定義為 1 - Bias 眯漩,而不是 -Bias ,我們可以補(bǔ)償非規(guī)格化數(shù)的尾數(shù)沒(méi)有隱含的開(kāi)頭的 1麻顶。
假如我們將圖 2-35 中的值的位表達(dá)式解釋為無(wú)符號(hào)整數(shù)赦抖,它們就是按升序排列的,就像它們表示的浮點(diǎn)數(shù)一樣辅肾。這不是偶然的——IEEE格式如此設(shè)計(jì)就是為了浮點(diǎn)數(shù)能夠使用整數(shù)排序函數(shù)來(lái)進(jìn)行排序队萤。
圖 2-36 展示了一些重要的單精度和雙精度浮點(diǎn)數(shù)的表示和數(shù)字值。依據(jù)圖 2-35 中展示的 8 位格式矫钓,我們能夠看出有 k 位階碼和 n 位小數(shù)的浮點(diǎn)表示的一般屬性要尔。
- 值 +0.0 總有一個(gè)全為 0 的位表示。
- 最小的正非規(guī)格化值的位表示新娜,是由最低有效位為 1 而其他所有位為 0 構(gòu)成的赵辕。它具有小數(shù)(和尾數(shù))值
和階碼值
。因此它的數(shù)字值是
概龄。
- 最大的非規(guī)格化值的位模式是由全為 0 的階碼字段和全為 1 的小數(shù)字段組成的还惠。它有小數(shù)(和尾數(shù))值
(我們寫(xiě)成
)和階碼值
。因此私杜,數(shù)值
蚕键,這僅比最小的規(guī)格化值小一點(diǎn)。
- 最小的正規(guī)格化值的位模式的階碼字段的最低有效位為 1 衰粹,其他位全為 0 锣光。它的尾數(shù)值
,而階碼值
铝耻。因此誊爹,數(shù)值
。
- 值 1.0 的位表示的階碼字段除了最高有效位等于 0 以外,其他位都等于 1替废。它的尾數(shù)值是
箍铭,而它的階碼值是
。
- 最大的規(guī)格化值的位表示的符號(hào)位為 0椎镣,階碼的最低有效位等于 0诈火,其他位等于 1。它的小數(shù)值
状答,尾數(shù)
(我們寫(xiě)作
)冷守。它的階碼值
,得到數(shù)值
整數(shù)值轉(zhuǎn)換成浮點(diǎn)形式惊科,相關(guān)的區(qū)域?qū)?yīng)于整數(shù)的低位拍摇,剛好在等于 1 的最高有效位之前停止(這個(gè)位就是隱含的開(kāi)頭的位 1),和浮點(diǎn)表示的小數(shù)部分的高位是相匹配的馆截。
2.4.4 舍入
因?yàn)楸硎痉椒ㄏ拗屏烁↑c(diǎn)數(shù)的范圍和精度充活,所以浮點(diǎn)運(yùn)算只能近似地表示實(shí)數(shù)運(yùn)算。因此蜡娶,對(duì)于值x混卵,能夠找到“最接近的”匹配值x',它可以用期望的浮點(diǎn)形式表示出來(lái)窖张。這就是舍入(rounding)運(yùn)算的任務(wù)幕随。
舍入方式有四種:
方式 | 1.40 | 1.60 | 1.50 | 2.50 | -1.50 |
---|---|---|---|---|---|
向偶數(shù)舍入 | 1 | 2 | 2 | 2 | -2 |
向零舍入 | 1 | 1 | 1 | 2 | -1 |
向下舍入 | 1 | 1 | 1 | 2 | -2 |
向上舍入 | 2 | 2 | 2 | 3 | -1 |
向偶數(shù)舍入是舍入到一個(gè)最接近的值。
2.4.5 浮點(diǎn)運(yùn)算
浮點(diǎn)加法不具有結(jié)合性宿接,例如赘淮,使用單精度浮點(diǎn),表達(dá)式 (3.14+1e10)-1e10 求值得到 0.0 —— 因?yàn)樯崛肽丽?3.14 會(huì)丟失梢卸。表達(dá)式 3.14+(1e10-1e10) 得出值 3.14。
浮點(diǎn)加法滿足了單調(diào)性屬性:如果 副女,那么對(duì)于任何 a蛤高、b 以及 x 的值,除了 NaN肮塞,都有
襟齿。無(wú)符號(hào)或補(bǔ)碼加法不具有這個(gè)實(shí)數(shù)(和整數(shù))加法的屬性姻锁。
浮點(diǎn)乘法不具有結(jié)合性枕赵。例如,單精度浮點(diǎn)情況下位隶,表達(dá)式 (1e201e20)1e-20 求值為拷窜,而 1e20(1e201e-20) 將得出 1e20。
浮點(diǎn)乘法在加法上不具備分配性。例如篮昧,單精度浮點(diǎn)情況下赋荆,表達(dá)式 1e20(1e20-1e20)求值為 0.0,而 1e201e20-1e20*1e20 會(huì)得出 NaN懊昨。
對(duì)于任何a窄潭、b和c,并且a酵颁、b和c都不等于 NaN嫉你,浮點(diǎn)乘法滿足下列單調(diào)性:
只要 ,就有
2.4.6 C 語(yǔ)言中的浮點(diǎn)數(shù)
所有的 C 語(yǔ)言版本提供了兩種不同的浮點(diǎn)數(shù)據(jù)類(lèi)型:float 和 double躏惋。
當(dāng)程序文件中出現(xiàn)下列句子時(shí)幽污,GUN 編譯器 GCC 會(huì)定義程序常數(shù) INFINITY(表示)和 NAN(表示 NaN):
#define _GUN_SOURCE 1
#include <math.h>
當(dāng)在 int、float 和 double 格式之間進(jìn)行強(qiáng)制類(lèi)型轉(zhuǎn)換時(shí)簿姨,程序改變數(shù)值和位模式的原則如下(假設(shè) int 是 32 位的):
- 從 int 轉(zhuǎn)換成 float距误,數(shù)字不會(huì)溢出,但是可能被舍入扁位。
- 從 int 或 float 轉(zhuǎn)換成 double准潭,因?yàn)?double 有更大的范圍(也就是可表示值的范圍),也有更高的精度(也就是有效位數(shù))贤牛,所以能夠保留精確的數(shù)值惋鹅。
- 從 double 轉(zhuǎn)換成 float,因?yàn)榉秶∫恍┭臭ぃ灾悼赡芤绯龀?
或
闰集。另外,由于精確度較小般卑,它還可能被舍入武鲁。
- 從 float 或者 double 轉(zhuǎn)換成 int,值將會(huì)向零舍入蝠检。例如沐鼠,1.999 將被轉(zhuǎn)換成 1,而 -1.999 將被轉(zhuǎn)換成 -1叹谁。