进制转换、字符编码

十进制、二进制、十六进制【进制转换】

1.十进制转二进制

1.1十进制整数转二进制

【除2取余,逆序排列】
具体做法是:用2整除十进制整数,可以得到一个商和余数;再用2去除商,又会得到一个商和余数,如此进行,直到商为0时为止,然后把先得到的余数作为二进制数的低位有效位,后得到的余数作为二进制数的高位有效位,依次排列起来。
例如:23[10] = 10111[2]
23 / 2 = 11 ......1
11 / 2 = 5  ......1
5  / 2 = 2  ......1
2  / 2 = 1  ......0
1  / 2 = 0  ......1
逆序排列为10111

1.2十进制小数转二进制
【乘2取整,顺序排列】
具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,如此进行,直到积中的小数部分为零,此时0或1为二进制的最后一位。或者达到所要求的精度为止。然后把取出的整数部分按顺序排列起来,先取的整数作为二进制小数的高位有效位,后取的整数作为低位有效位。
例如:0.6[10] =0.101[2]
0.625 * 2 = 1.25 ======取出整数部分1
0.25  * 2 = 0.5  ======取出整数部分0
0.5   * 2 = 1    ======取出整数部分1

2.二进制转十进制
从左到右用二进制的每个数去乘以2的相应次方。
例如:1101.01[2] = 13.25[10]
1101.01 = 1*2的0次 + 0*2的1次 + 1*2的2次 + 1*2的3次【前面为整数部分】  +  0*2的-1次 + 1*2的-2次 = 1+0+4+8+0+0.25=13.25

3.十进制转十六进制
16进制即逢16进1,其中用A,B,C,D,E,F(字母不区分大小写)这六个字母来分别表示10,11,12,13,14,15。
故而有16进制每一位上可以是从小到大为0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F共16个大小不同的数。

十进制转十六进制 同理 十进制转二进制
【除16取余,逆序排列】
例如:10997[10] = 2AF5[16]
10997 / 16 = 687......5
687   / 16 = 42 ......15
42    / 16 = 2  ......10
2     / 16 = 0  ......2
所以10997[10] = 2 + A + F + 5 = 2AF5[16]

4.十六进制转十进制
同理二进制转十进制
例如:2AF5[16] = 10997[10]
5 * 16的0方 = 5
F * 16的1方 = 240
A * 16的2方 = 2560
2 * 16的3方 = 8192
所以2AF5[16] = 5 + 240 + 2560 + 8192 = 10997[10]
==============================================================================================
字符编码

为什么要进行编码?这些编码的关系如何,如ASCII,IOS-8859-1,GB2312,GBK,Unicode之间的关系?

为何需要编码?
  我们知道,所有的信息最终都表示为一个二进制的字符串,每一个二进制位(bit)有0和1两种状态。当我们需要把字符'A'存入计算机时,应该对应哪种状态呢,存储时,我们可以将字符'A'用01000010(这个随便编的)二进制字符串表示,存入计算机;读取时,再将01000010还原成字符'A'。那么问题来了,存储时,字符'A'应该对应哪一串二进制数呢,是01000010?或者是10000000 11110101?说白了,就是需要一个规则。这个规则可以将字符映射到唯一一种状态(二进制字符串),这就是编码。而最早出现的编码规则就是ASCII编码,在ASCII编码规则中,字符'A'既不对应01000010,也不对应1000 0000 11110101,而是对应01000001。

1.ASCII

       这套编码规则是由美国定制,一共规定了128个字符的编码,比如空格"SPACE"是32(十进制)(二进制00100000),大写的字母A是65(二进制01000001)。这128个符号(包括 32个不能打印出来的控制符号),只占用了一个字节(8 bit)的后面7位,最前面的1位统一规定为0。总共才有128个字符编码,一个字节都没有用完,这好像似乎有点太少了。于是乎,就开始压榨最高位,对其为1时也进行编码,利用最高位进行编码的方式就称为非ASCII编码,如ISO-8859-1编码。

2.ISO-8859-1
这套编码规则由ISO组织制定。是在 ASCII 码基础上又制定了一些标准用来扩展ASCII编码,即 00000000(0) ~ 01111111(127) 与ASCII的编码一样,对 10000000(128) ~ 11111111(255)这一段进行了编码,如将字符§编码成 10100111(167)。ISO-8859-1编码也是单字节编码,最多能够表示256个字符。Latin1是ISO-8859-1的别名,有些环境下写作Latin-1。但是,即使能够表示256个字符,对中文而言,还是太少了,一个字节肯定不够,必须用多个字节表示。而常见的中文编码方式有GB2312、BIG5、GBK。

3.GB2312
GB2312其对所收录字符进行了"分区"处理,共94个区,区从1(十进制)开始,一直到94(十进制),每区含有94个位,位从1(十进制)开始,一直到94(十进制),共8836(94 * 94)个码位,这种表示方式也称为区位码,GB2312是双字节编码,其中高字节表示区,低字节表示位。各区具体说明:
01-09区收录除汉字外的682个字符,有164个空位(9 * 94 - 682)。
10-15区为空白区,没有使用。
16-55区收录3755个一级汉字(简体),按拼音排序。
56-87区收录3008个二级汉字(简体),按部首/笔画排序。
88-94区为空白区,没有使用。

区位码的表示范围为0101 - 9494(包含了空的区位码)。那么根据区位码如何算出GBK2312编码呢?
将区(十进制) 和 位(十进制)分别转化为十六进制,并加上A0,组合区和位,区在高字节,位在低字节,得到GB2312编码。
例如:'李'字的区位码为3278(表示在32区,78位)。
1. 将32(区)转化为十六进制为20。
2. 加上A0为C0。
3. 将78(位)转化为十六进制为4E。
4. 加上A0为EE。
5. 组合区和位,为C0EE。
6. 得到GB2312编码,即'李'字的GB2312编码为C0EE。

GB2312用两个字节编码,采用分区编码,总共编码的中文个数为6763(3755 + 3008)。这些汉字只是最常用的汉字,已经覆盖中国大陆99.75%的使用频率。
但是,还有一些汉字在GB2312中没有被编码,如'镕'字,在GB2312中就没有被编码,这样就导致了问题,随之就出现了主流的GBK编码。
在讲解GBK编码之前,我们另外讲解一下BIG5编码。

4.BIG5
BIG5采用双字节编码,使用两个字节来表示一个字符。高位字节使用了0x81-0xFE,低位字节使用了0x40-0x7E,及0xA1-0xFE。该编码是繁体中文字符集编码标准,共收录13060个中文字,其中有二字为重复编码,即“兀、兀”(A461及C94A)和“嗀、嗀”(DCD1及DDFC)。具体的分区如下: 
8140-A0FE 保留给使用者自定义字符(造字区)
A140-A3BF 标点符号、希腊字母及特殊符号。其中在A259-A261,收录了度量衡单位用字:兙兛兞兝兡兣嗧瓩糎。
A3C0-A3FE 保留。此区没有开放作造字区用。
A440-C67E 常用汉字,先按笔划再按部首排序。
C6A1-F9DC 其它汉字。
F9DD-F9FE 制表符。

注意,BIG5编码与GBK编码没有什么关系。

5.GBK
GBK编码扩展了GB2312,完全兼容GB2312编码(如'李'字的GBK、GB2312编码均为C0EE),但其不兼容BIG5编码。即如果使用GB2312编码,使用GBK解码是完全正常的
相比于GB2312编码,GBK编码了更多汉字,如'镕'字。GBK编码依然采用双字节编码方案,其编码范围:8140-FEFE,剔除xx7F码位,共23940个码位。能表示 21003 个汉字。

6.Unicode
       有两个独立的, 创立单一字符集的尝试. 一个是国际标准化组织(ISO)的 ISO 10646 项目, 另一个是由多语言软件制造商组成的协会组织的 Unicode 项目. 在1991年前后, 两个项目的参与者都认识到, 世界不需要两个不同的单一字符集. 它们合并双方的工作成果, 并为创立一个单一编码表而协同工作. 两个项目仍都存在并独立地公布各自的标准, 但 Unicode 协会和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 标准的码表兼容, 并紧密地共同调整任何未来的扩展。
       Unicode是指一张表,里面包含了可能出现的所有字符,每个字符对应一个数字,这个数字称为码点(Code Point),如字符'H'的码点为72(十进制),字符'李'的码点为26446(十进制)。Unicode表包含了1114112个码点,即从000000(十六进制) - 10FFFF(十六进制)。地球上所有字符都可以在Unicode表中找到对应的唯一码点。
Unicode将码空间划分为17个平面,从00 - 10(十六进制,最高两位),即从0 - 16(十进制),每个平面有65536个码点(2^16),其中最重要的是第一个Unicode平面(码位从0000 - FFFF),包含了最常用的字符,该平面被称为基本多语言平面(Basic Multilingual Plane),缩写为BMP,其他平面称为辅助平面(Supplementary Planes),在基本多文种平面內, 从D800到DFFF之间的码位区段是永久保留不映射到字符的, 因此UTF-16编码巧妙的利用了这保留下来的码位来对辅助平面内的字符进行编码,

       Unicode只是一个符号集,只规定的字符所对应的码点,并没有指定如何存储,如何进行存储出现了不同的编码方案,关于Unicode编码方案主要有两条主线:UCS和UTF。UTF主线由Unicode Consortium进行维护管理,UCS主线由ISO/IEC进行维护管理。

7.UTF

7.1 UTF-8

UTF-8是一种变长编码方式,使用1-4个字节进行编码。UTF-8完全兼容ASCII,对于ASCII中的字符,UTF-8采用的编码值跟ASCII完全一致。UTF-8是Unicode一种具体的编码实现。UTF-8是在互联网上使用最广的一种Unicode的编码规则,因为这种编码有利于节约网络流量(因为变长编码,而非统一长度编码)。关于Unicode码点如何转化为UTF-8编码,可以参照如下规则:
①对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
②对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

Unicode符号范围                  |    UTF-8编码方式

 (十六进制) (十进制)            |   (二进制)
------------------------------------------------------------------------------------
0000 0000 - 0000 007F (0-127)           |    0xxxxxxx
0000 0080 - 0000 07FF (128-2047)        |    110xxxxx 10xxxxxx
0000 0800 - 0000 FFFF (2048-65535)      |     1110xxxx 10xxxxxx 10xxxxxx
0001 0000 - 0010 FFFF (65536-1114111)   |    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

说明:字符'A'的Unicode码点为65(十进制),根据上表,在第一行范围,则字符'A'的UTF-8编码为01000001,中文字符'李'的Unicode码点为26446(十进制),二进制为01100111 01001110,十六进制为674E。根据上表,在第三行范围,则将'李'二进制代码从低位到高位依次填入x中,不足的填入0。得到UTF-8编码为11100110 10011101 10001110,即E69D8E(十六进制)。
          由上述编码规则可知,0000 0000 - 0000 FFFF(第一行到第三行)为Unicode第一个平面(基本多语言平面),而0001 0000 - 10 FFFF(第四行)为Unicode其他平面(辅助平面)。在基本多语言平面对应了绝大多数常用的字符。对于大于65535(十进制)的码点,即在辅助平面上的码点,需要使用4个字节来进行UTF-8编码。

7.2 UTF-16
UTF-8是不定长的编码,使用1、2、3、4个字节编码,而UTF-16则只使用2或4个字节编码。UTF-16也是Unicode一种具体的编码实现。关于Unicode如何转化为UTf-16编码规则如下:
① 若Unicode码点在第一平面(BPM)中,则使用2个字节进行编码。
② 若Unicode码点在其他平面(辅助平面),则使用4个字节进行编码。

参考: http://www.cnblogs.com/leesf456/p/5317574.html


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值