C++有符号和无符号数的转换
本文轉(zhuǎn)自:http://www.94cto.com/index/Article/content/id/59973.html
1.引例:
?
今天在做了一道關(guān)于有符號(hào)數(shù)和無(wú)符號(hào)數(shù)相互轉(zhuǎn)換及其左移/右移的問(wèn)題,被它們之間的轉(zhuǎn)換原理和位移原理搞得頭大了。真的很后悔本科的時(shí)候沒(méi)有認(rèn)真學(xué)習(xí)《計(jì)算機(jī)組成原理》/《計(jì)算機(jī)操作系統(tǒng)》等計(jì)算機(jī)基礎(chǔ)課程。以下是我根據(jù)相關(guān)知識(shí)回顧和整理的材料,如有和某某的文章有雷同之處,請(qǐng)勿見(jiàn)怪。另外也希望看到這篇文章的同志們能夠有所收獲吧。
1 #include <cstdio> 2 #include <iostream> 3 using namespace std; 4 5 int main() 6 { 7 unsigned short int ui; 8 signed short int si; 9 ui = (unsigned short int)0x8000u; 10 si = (signed short int)0x8000; 11 printf("ui = %u\n",ui); 12 printf("si = %d\n",si); 13 ui = ui>>1; 14 si = si>>1; 15 printf("ui = %u\n",ui); 16 printf("si = %d\n",si); 17 cout<<"------------------------------"<<endl; 18 19 ui = (unsigned short int)0x8000u; 20 si = (signed short int)0x8000; 21 printf("%u\n",ui); 22 printf("%d\n",si); 23 ui = ((signed short int)ui>>1);//先類型轉(zhuǎn)換,再移位, 24 si = ((unsigned short int)si>>1); 25 printf("%u\n",ui); 26 printf("%d\n",si); 27 cout<<"------------------------------"<<endl; 28 29 ui = (unsigned short int)0x8000u; 30 si = (signed short int)0x8000; 31 printf("%u\n",ui); 32 printf("%d\n",si); 33 ui = ui<<1; 34 si = si<<1; 35 printf("%u\n",ui); 36 printf("%d\n",si); 37 cout<<"-------------------------------"<<endl; 38 39 ui = (unsigned short int)0x8000u; 40 si = (signed short int)0x8000; 41 printf("%u\n",ui); 42 printf("%d\n",si); 43 ui = ((signed short int)ui<<1); 44 si =((unsigned short int)si<<1); 45 printf("%u\n",ui); 46 printf("%d\n",si); 47 return 0; 48 }運(yùn)行結(jié)果
2.概念
?在計(jì)算機(jī)中,可以區(qū)分正負(fù)類型的數(shù),成為“有符號(hào)數(shù)”(signed);無(wú)正負(fù)類型的數(shù)(只有整數(shù)類型),成為“無(wú)符號(hào)數(shù)”(unsigned)。簡(jiǎn)明的說(shuō),無(wú)符號(hào)說(shuō)就是其所有的位數(shù)都用來(lái)表示數(shù)值的大小,有符號(hào)數(shù)除最高位來(lái)表示數(shù)值的正負(fù)外(0表示正數(shù);1表示負(fù)數(shù)),其余各位用來(lái)表示數(shù)值的大小。舉個(gè)例子說(shuō)明一下:十機(jī)制數(shù) 正數(shù)255? 二進(jìn)制表達(dá)形式:1111 1111
十機(jī)制數(shù) 負(fù)數(shù)-1???? 二進(jìn)制表達(dá)形式:1111 1111?
可見(jiàn)-1的二進(jìn)制的最高位為紅色的1,可是為什么其表達(dá)形式為1111 1111而不是1000 0001呢?這就關(guān)于任何數(shù)在計(jì)算機(jī)內(nèi)是以補(bǔ)碼形式存儲(chǔ)問(wèn)題。下面會(huì)介紹的,在此先不詳細(xì)說(shuō)明了。
3.存儲(chǔ)范圍
從前面的介紹可以知道,由于有符號(hào)數(shù)的最高位被拿來(lái)用作符號(hào)位,所以它所能夠表達(dá)的最大數(shù)值要小于無(wú)符號(hào)數(shù)所能夠表達(dá)的最大數(shù)值。還是舉個(gè)例子來(lái)說(shuō)明一下吧:
無(wú)符號(hào)數(shù):1111 1111 十進(jìn)制值:255
有符號(hào)數(shù):0111 1111 十進(jìn)制值:127
這是有人可能會(huì)提出這樣的疑問(wèn):有符號(hào)數(shù)所能夠表達(dá)的數(shù)值范圍會(huì)不會(huì)小于無(wú)符號(hào)數(shù)所能夠表達(dá)的數(shù)值范圍呢?
呵呵,答案是否定的!雖然有符號(hào)數(shù)在表達(dá)最大值上的能力減弱了,但是它能夠表達(dá)負(fù)數(shù)。負(fù)數(shù)的個(gè)數(shù)可以彌補(bǔ)其不足。來(lái)讓我們比較一下:
一個(gè)字節(jié)的無(wú)符號(hào)數(shù)的表達(dá)數(shù)值范圍是:[0,255]
一個(gè)字節(jié)的有符號(hào)數(shù)的表達(dá)數(shù)值范圍是:[-128,0),[0,127]
可見(jiàn)它們都能夠表示256個(gè)數(shù)。
4.各種碼(原碼/反碼/補(bǔ)碼)
有些人也許會(huì)這樣認(rèn)為"-1"(雙字節(jié))在計(jì)算機(jī)中的表達(dá)形式為1000 0000 0000 0001,可是實(shí)際上不是的。計(jì)算機(jī)是以其補(bǔ)碼的形式進(jìn)行表達(dá)的,即“-1”(雙字節(jié))的表達(dá)形式是1111 1111 1111 1111。
說(shuō)一下各種碼的概念吧。
原碼:一個(gè)整數(shù),按照絕對(duì)值的大小轉(zhuǎn)換成二進(jìn)制數(shù),最高位為符號(hào)位。
反碼:將原碼除最高位(符號(hào)位)外,其余各位按位取反,所得到的二進(jìn)制碼。正數(shù)的反碼為原碼。
補(bǔ)碼:反碼最低位加1即為補(bǔ)碼。
關(guān)于負(fù)數(shù)的補(bǔ)碼求法說(shuō)明一下,先得到其反碼,之后將反碼加1即可。有些大神根據(jù)其原碼,閉眼即得,這種能力需要修煉一下啊。
這時(shí)有些人可能會(huì)說(shuō),為什么要引入補(bǔ)碼的形式呢?直接按照原碼存儲(chǔ)不就省事很多嗎?嘿嘿,要記住,有些事情并不是你想省事就能省事的。好了來(lái)欣賞一下補(bǔ)碼的優(yōu)勢(shì)吧。
計(jì)算機(jī)的帶符號(hào)數(shù)用補(bǔ)碼表示的優(yōu)點(diǎn):
1負(fù)數(shù)的補(bǔ)碼與對(duì)應(yīng)正數(shù)的補(bǔ)碼之間的轉(zhuǎn)換可以用同一種方法-求補(bǔ)運(yùn)算完成,可以簡(jiǎn)化硬件。 2 可將減法變?yōu)榧臃?#xff0c;這樣減法就可以用加法器進(jìn)行計(jì)算了。 3 兩個(gè)用補(bǔ)碼表示的數(shù)相加時(shí),如果最高位(符號(hào)位)有進(jìn)位,則進(jìn)位被舍棄。
心算求補(bǔ)(大神求補(bǔ)算法):
從最低位開(kāi)始至找到的第一個(gè)1均不變,符號(hào)位不變,這之間的各位“求反”(0變1;1變0)。
原碼:1010 1001? 補(bǔ)碼:1101 0111.
5.有符號(hào)數(shù)與無(wú)符號(hào)數(shù)的相互轉(zhuǎn)換
無(wú)符號(hào)整數(shù)和有符號(hào)整數(shù)之間進(jìn)行強(qiáng)制類型轉(zhuǎn)換時(shí),位模式不改變。
有符號(hào)數(shù)轉(zhuǎn)換為無(wú)符號(hào)數(shù)時(shí),負(fù)數(shù)轉(zhuǎn)換為大的正數(shù),相當(dāng)于在原值上加上2的n次方,而正數(shù)保持不變。
無(wú)符號(hào)數(shù)轉(zhuǎn)換為有符號(hào)數(shù)時(shí),對(duì)于小的數(shù)將保持原值,對(duì)于大的數(shù)將轉(zhuǎn)換為負(fù)數(shù),相當(dāng)于原值減去2的n次方。
當(dāng)表達(dá)式中存在有符號(hào)數(shù)和無(wú)符號(hào)數(shù)類型時(shí),所有的操作都自動(dòng)轉(zhuǎn)換為無(wú)符號(hào)類型。可見(jiàn)無(wú)符號(hào)數(shù)的運(yùn)算優(yōu)先級(jí)高于有符號(hào)數(shù)。
unsigned int a = 20; signed int b = -130;?運(yùn)算一下結(jié)果是 b>a?
6.轉(zhuǎn)換大餐
有符號(hào)數(shù)的轉(zhuǎn)換
| 原類型 | 目標(biāo)類型 | 轉(zhuǎn)換方法 |
| ?char | short | 符號(hào)位擴(kuò)展 |
| char | long | 符號(hào)位擴(kuò)展 |
| char | unsigned char | 最高符號(hào)位失去位意義,變?yōu)閿?shù)據(jù)位 |
| char | unsigned short | 符號(hào)位擴(kuò)展到short;然后從short轉(zhuǎn)到unsigned short |
| char | unsigned long | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)換到unsigned long |
| char | float | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)到float |
| char | double | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)換到double |
| char | long double | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)換到long double |
| short | char | 保留低位字節(jié) |
| short | long | 符號(hào)位擴(kuò)展 |
| short | unsigned char | 保留低位字節(jié) |
| short | unsigned short | 最高為失去意義,變?yōu)閿?shù)據(jù)位 |
| short | unsigned long | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)到unsigned long |
| short | float | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)到float |
| short | double | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)到double |
| short | long double | 符號(hào)位擴(kuò)展到long;然后從long轉(zhuǎn)換到long double |
| long | char | 保留低位字節(jié) |
| long | short | 保留低位字節(jié) |
| long | unsigned char | 保留低位字節(jié) |
| long | unsigned short | 保留低位字節(jié) |
| long | unsigned long | 最高為失去意義,變?yōu)閿?shù)據(jù)位 |
| long | float | 使用單精度浮點(diǎn)數(shù)表示,可能失去精度 |
| long | double | 使用單精度浮點(diǎn)數(shù)表示,可能失去精度 |
| long | long double | 使用單精度浮點(diǎn)數(shù)表示,可能失去精度 |
無(wú)符號(hào)數(shù)的轉(zhuǎn)換
| 原類型 | 目標(biāo)類型 | 轉(zhuǎn)換方法 |
| unsigned char | char | 最高為作符號(hào)位 |
| unsigned char | short | 0擴(kuò)展 |
| unsigned char | long | 0擴(kuò)展 |
| unsigned char | unsigned short | 0擴(kuò)展 |
| unsigned char | unsigned long | 0擴(kuò)展 |
| unsigned char | float | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到float |
| unsigned char | double | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到double |
| unsigned char | long double | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到long double |
| unsigned short | char | 保留低位字節(jié) |
| unsigned short | short | 最高為作符號(hào)位 |
| unsigned short | long | 0擴(kuò)展 |
| unsigned short | unsigned char | 保留低位字節(jié) |
| unsigned short | unsigned long | 0擴(kuò)展 |
| unsigned short | float | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到float |
| unsigned short | double | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到double |
| unsigned long | long double | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到long double |
| unsigned long | char | 保留低位字節(jié) |
| unsigned long | short | 保留低位字節(jié) |
| unsigned long | long | 最高位作符號(hào)位 |
| unsigned long | unsigned char | 保留低位字節(jié) |
| unsigned long | unsigned short | 保留低位字節(jié) |
| unsigned long | float | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到float |
| unsigned long | double | 直接轉(zhuǎn)換到double |
| unsigned long | long double | 轉(zhuǎn)換到long;然后從long轉(zhuǎn)換到long double |
7.各種數(shù)據(jù)類型所占字節(jié)
32位平臺(tái)下:
?ps:文中若有不當(dāng)之處,請(qǐng)指出!
?
轉(zhuǎn)載于:https://www.cnblogs.com/LCCRNblog/p/5225065.html
總結(jié)
以上是生活随笔為你收集整理的C++有符号和无符号数的转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: sql多行合成一行的解决方法
- 下一篇: oracle 11g安装过程中问题:找不