對二值信號進行存儲和執(zhí)行計算的電子電路非常簡單和可靠。
重要的三中數(shù)字表示:
- 無符號 -- 基于傳統(tǒng)的二進制表示法,表示大于或者等于零的數(shù)字。
- 補碼 -- 表示有符號整數(shù)的最常見方式,有符號整數(shù)就是可以為正或者為負得數(shù)字。
- 浮點數(shù) -- 表示實數(shù)的科學記數(shù)法的以二為基數(shù)的版本。
計算機的表示法是用有限數(shù)量的位來對一個數(shù)字編碼。由于表示的精度有限,浮點運算是不可結(jié)合的。
整數(shù)運算和浮點運算會有不同的數(shù)學屬性是因為他們處理數(shù)字表示有限性的方式不同--整數(shù)的表示雖然只能編碼一個相對較小的數(shù)值范圍,但是這種表示是精確的;而浮點數(shù)雖然可以編碼一個較大的數(shù)值范圍,但是這種表示只是近似的。
整數(shù)運算--精確的。
浮點運算--非精確的。
2.1 信息存儲
大多數(shù)計算機使用8位的塊,或者字節(jié),作為最小的可尋址的存儲器單位,而不是在存儲器中訪問單獨的位。
C語言中一個指針的值(無論是指向一個整數(shù)、一個結(jié)構(gòu)或某個其他程序?qū)ο螅┒际且阅硞€存儲塊的第一個字節(jié)的虛擬地址。
在C語言中,以0x或者0X開頭得數(shù)字常量被認為是十六進制的值。字符A~F既可以是大寫,也可以是小寫,甚至是大小寫混合。
十六進制轉(zhuǎn)換為二進制:首先將每4位分為一組,再把它轉(zhuǎn)換為十六進制。不過需要注意,如果位得總數(shù)不是4的倍數(shù),最左邊得一組可以少于4位,前面用0補足,然后將每個4位組轉(zhuǎn)換為相應(yīng)的十六進制數(shù)字。
當值x是2的非負整數(shù)n次冪時,也就是x=2^n,我們可以很容易地將x攜程十六進制形式,只要記?。?br>
x的二級制表示就是1后面跟n個0.
十六進制數(shù)字0代表4個二級制0。
所以,當n表示成i+4j的形式,其中0≤i≤3時,我們可以把寫成開頭得十六進制數(shù)字為 1(i=0)、2(i=1)、4(i=2)、8(i=3),后面跟隨著j個十六進制的0.
比如: x=2048=2^11
于是有: n = 11 = 3+4*2 從而得到十六進制表示 0x800
2.1.2 字
每臺計算機都有一個字長(word size),指明整數(shù)和指針數(shù)據(jù)的標稱大小(nominal size)。因為虛擬地址是通過一個字來編碼的。所以字長決定的最重要的系統(tǒng)參數(shù)就是虛擬地址空間得最大大小。也就是說,對于一個字長為w位得機器而言,虛擬地址的范圍是0~2(w-1),程序最多訪問2w個字節(jié)。
2.1.3 數(shù)據(jù)大小
C的數(shù)據(jù)類型大小:
char -- 1個字節(jié)。
short int -- 2個字節(jié)
int -- 4個字節(jié)
long int-- 使用機器的全字長,如果是32位則4字節(jié),如果64為則8字節(jié)
long long int-- 允許64位整數(shù),使用8個字節(jié)。對于32位機器而言,編譯器必須把這種數(shù)據(jù)類型的操作編譯成一系列32位操作的代碼。
float -- 4個字節(jié)
double-- 8個字節(jié)
char* -- 機器的全字長,32位是4個字節(jié),64位是8個字節(jié)。
需要注意:許多程序員假設(shè)一個聲明為int類型得程序?qū)ο竽鼙挥脕泶鎯σ粋€指針。這在大多數(shù)32位得機器上能正常工作,但是在一臺64位得機器上卻會導致問題。(因為64位下int是4字節(jié),而指針是8字節(jié)。)
2.1.4 尋址和字節(jié)順序
在幾乎所有的機器上,多字節(jié)對象都被存儲為連續(xù)的字節(jié)序列,對象的地址為嗦使用字節(jié)中最小的地址。
例如:一個類型為int得變量x的地址為0x100,也就是說,地址表達式&x的值為0x100。那么,x的4個字節(jié)被存儲在存儲器的0x100,0x101,ox102,ox103位置。
在存儲器存儲中,有大端法和小端法的區(qū)分:
大端法 -- 最高有效字節(jié)在最前面。IBM和SUN采用此種規(guī)則。
小端法 -- 最低有效字節(jié)在最前面。Intel兼容機采用此種規(guī)則。
許多比較新的微處理器使用雙端法,也就是說可以把他們配置為大端或者小端的機器運行。
對于int類型的x,位于地址0x100處,它得十六進制值為0x1234567 ,地址范圍為0x100~0x103字節(jié),其排列順序依賴于機器類型。
大端法 -- 01(ox100) 23(0x101) 45(0x102) 67(0x103)
小端法 -- 67(ox100) 45(0x101) 23(0x102) 01(0x103)
一般情況下,機器所使用的字節(jié)順序?qū)ξ覀儊碚f是透明的,不可見的。無論使用哪種類型的機器編譯程序都會得到同樣的結(jié)果。
除非在編寫網(wǎng)絡(luò)程序的時候,才需要注意這個問題。
為了避免這類問題,網(wǎng)絡(luò)應(yīng)用程序的代碼編寫必須遵守已建立的關(guān)于字節(jié)順序的規(guī)則,以確保發(fā)送機器將它得內(nèi)部表示轉(zhuǎn)換成網(wǎng)絡(luò)標準,而接收方機器則將網(wǎng)絡(luò)標準轉(zhuǎn)換為它得內(nèi)部表示。
對于任一位向量a,有a^a =0 。
2.1.9 C語言中的位運算和邏輯運算
C語言中的位運算:
| 或
& 與
~ 取反
^ 異或 當p=1且q=0,或者p=0且q=1時, p^q = 1
C語言中的邏輯運算:
|| 或 or
&& 與 and
! 非 not
邏輯運算認為所有非零的參數(shù)都表示true,而參數(shù)0表示false。
邏輯運算&&和||與他們對應(yīng)的位級運算&和|之間的第二個重要的區(qū)別是,如果對第一個參數(shù)求值就能確定表達式的結(jié)果,那么邏輯運算符就不會對第二個參數(shù)求值。
2.1.0 C語言中的移位運算
左移、右移
右移支持兩種:邏輯右移和算術(shù)右移。
邏輯右移在左端補0。
算術(shù)右移是在左端補最高有效位的值。
x = 01100001 10010101
x》4 (邏輯右移) 00000110 00001001
x》4 (算術(shù)右移) 00000110 11111001
C語言中并沒有明確定義應(yīng)該使用哪種類型的右移。對于無符號數(shù)據(jù)(也即是以 unsigned聲明開通的整型對象),邏輯右移是必須得。
幾乎所有的編譯器、機器組合都對有符號數(shù)據(jù)使用算術(shù)右移,且許多程序員也都假設(shè)機器會使用算術(shù)右移。
另外,Java對于如何進行右移有明確的定義。
x》k 會將x算術(shù)右移k個位置。
x>>>k 會對x做邏輯右移。
在許多機器上,當移位位數(shù)k超過了機器的字長w時,移位移的是w mod k 位。
比如在32位機器上移位40位,則只是移8位。
int lval = oxFEDCBA98 <<32 = oxFEDCBA98
int aval = oxFEDCBA98 >>36 = 0xFFEDCBA9
unsigned uval = oxFEDCBA98u >>40 = ox00FEDCBA
不過C語言沒有對這種行為進行保障,所以移位數(shù)量應(yīng)該保持小于字長。
另一方面,Java特別要求位移數(shù)量應(yīng)該按照之前講的求模的方法來計算。
加法減法的優(yōu)先級比移位運算要高。
所以: 1<<2+3<<4 = 1<<(2+3)<<4 = (1<<(2+3))<<4 = 512
在拿不準時,請用括號表明運算順序。