字符编码--第2章 数的存储

第2章 数的存储

第1节 机器数

计算机中,表示数和数的符号的二进制数,叫做机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1。

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。那么,这里的 00000011 和 10000011 就是机器数。

机器数可用不同的码制来表示,常用的有原码、补码和反码表示法。

第2节 真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

第3节 有符号数处理

在计算机运算中,有符号数的表示需要将负数编码为二进制形式。在数学中,任意基数的负数都在最前面加上“?”符号来表示。然而在计算机硬件中,数字都以无符号的二进制形式表示,因此需要一种编码负号的方法。当前有四种方法,用于扩展二进制数字系统,来表示有符号数:原码(sign-and-magnitude),反码(ones‘ complement),补码(two‘s complement),以及移码excess-N。

1.原码

原码就是符号位加上真值的绝对值,符号及值(sign & magnitude)的处理法是分配一个符号位(sign bit)来表示这个符号:设置这个位(通常为最高有效位)为0表示一个正数,为1表示一个负数。数字中的其它位指示数值(或者绝对值)。因此一个字节只有7位(除去符号位),数值的范围从0000000(0)到1111111(127)。这样当你增加一个符号位(第八位)后,可以表示从?12710到+12710的数字。这种表示法导致的结果就是可以有两种方式表示零,00000000(0)与10000000(?0),这大大增加数码电路的复杂性和设计难度。CPU亦须执行两次比较,来测试运算结果是否为零。

十进制数?43用原码方法编码成八位的结果为10101011。

这种方法被直接比较于常用的符号表示法(放置一个“+”或者“?”在数字的数值之前)。一些早期的二进制电脑(例如IBM 7090)使用这种表示法,也许是由于它与通用用途的自然联系。原码是最常用的表示浮点数的方法。IEEE二进位浮点数算术标准(IEEE 754)采用最高有效位作为符号位,因此可表示正负零及正负无限。

2.反码

另一方面,一种叫做反码的系统也可以用于表示负数(注:正数与原码形式一样,无需取反)。一个负数的二进制数反码形式为其绝对值部分按位取反(即符号位不变,其余各位按位取反)。同原码表示一样,0的反码表示形式也有两种:00000000(+0)与11111111(?0)。

举例来说,原码10101011(-43)的反码形式为11010100(?43)。有符号数用反码表示的范围为?(2N?1?1)到(2N?1?1),以及+/?0。传统的表示为?12710到+12710,以及00000000(+0)或者11111111(?0)。

正数的反码是其本身, 负数的反码是在其原码的基础上, 符号位不变,其余各个位取反。注意负数的反码只需按位求数值的补就可以得到,符号不需要变动。

3.补码

补码(2‘s complement)是一种用二进制表示有号数的方法,也是一种将数字的正负号变号的方式,常在计算机科学中使用。在台湾和香港称为二补数。数据在计算机中主要是以补码的形式存储的。

一个数字的补码就是将该数字作比特反相运算(即一补数或反码),再将结果加 1。在补码系统中,一个负数就是用其对应正数的补码来表示。正数的补码就是其本身,负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1) 。

补码回避了0有多种表示的问题以及循环进位的需要。在补码表示中,负数以位模式表示为正值的反码加1(当作无符号数)。

在补码表示中,只有一个0(00000000)。求一个数的否(无论是负数还是正数)需要反转所有位,然后加1。一对补码整数相加等价于一对无符号数相加(除了溢出检测,如果能够做到的话)。比如,从旁边的表格可以看出,127与?128的补码表示相加就与无符号数127及128相加具有相同的结果。

补码系统的最大优点是可以在加法或减法处理中,不需因为数字的正负而使用不同的计算方式。只要一种加法电路就可以处理各种有号数加法,而且减法可以用一个数加上另一个数的补码来表示,因此只要有加法电路及补码电路即可完成各种有号数加法及减法,在电路设计上相当方便。

另外,补码系统的 0 只有一个表示方式,这点和一补数系统不同(在一补数系统中,0 有二种表示方式),因此在判断数字是否为 0 时,只要比较一次即可。

8-bit补码系统的整数。它的可表示的范围包括-128到127,总共256 (28)个整数。

以下用 4 比特的补码数字来说明补码系统的数字表示方式。

在表示正数和零时,二补数数字和一般二进制一样,唯一的不同是在补码系统中,正数的最高比特恒为 0,因此4 比特的补码正数,最大数字为 0111 (7)。

补码数字的负数,最高比特恒为 1,4 比特补码的数字中,最接近 0 的负数为 1111 (-1),以此类推,因此绝对值最大的负数是 1000 (-8)。

在一般 n 比特的二进制数字中,最高有效比特(MSB) 第 n 比特代表的数字为 2n?1。不过,在 n 比特的补码系统中,最高有效比特(MSB) 第 n 比特表示符号比特,若符号比特为 0,数字为正数或 0,若符号比特为 1,数字为负数。

求负数补码表示的方法:

  (1)写出与该负数相对应的正数的补码

  (2)按位求反

  (3)末位加一

  例:假设机器字长为8位,求-46的补码。

    + 46的补码表示为: 0010 1110

    按位求反:     1101 0001

    末位加一      1101 0010

    所以,[-46]补码 = D2H

符号扩展:是指一个数从位数较少扩展到位数较多,如从8位扩展到16位,或从16位扩展到32位。

  对于用补码表示的数,正数的符号扩展在前面补0,负数的符号扩展在前面补1,假设机器字长为16位,[+46]补码 = 002EH,[-46]补码 = FFD2H。

n位补码的表数范围

  8位二进制数可以表示=256个数,16位二进制数可以表示=65536个数,当它们是补码表示的带符号数时,8位二进制的表数范围是 -128 N +127,

16位二进制的表数范围是 -32768  N  +32767。

  n位补码的表数范围是:

4.移码

移码,是将二进制原码无符号整数所代表的值,减去一个预设值。

标准移码,预设值为二进制原码表示的最大整数的一半。 一个数的标准移码和补码,最高位相反,其余各位均相同。

#include <stdio.h>

int main(int argc, char * argv) {

char a;

short b;

a = 127;

b = (short)127;

printf("a=%08X,b=%d.\n", a, b);

a = 128;

b = (short)128;

printf("a=%08X,b=%d.\n", a, b);

a = 1;

b = (short)1;

printf("a=%08X,b=%d.\n", a, b);

a = 0;

b = (short)0;

printf("a=%08X,b=%d.\n", a, b);

a = -0;

b = (short)-0;

printf("a=%08X,b=%d.\n", a, b);

a = -1;

b = (short)-1;

printf("a=%08X,b=%d.\n", a, b);

a = -128;

b = (short)-128;

printf("a=%08X,b=%d.\n", a, b);

a = (char) -129;

b = (short)-129;

printf("a=%08X,b=%d.\n", a, b);

return 0;

}

a=0000007F,b=127.

a=FFFFFF80,b=128.

a=00000001,b=1.

a=00000000,b=0.

a=00000000,b=0.

a=FFFFFFFF,b=-1.

a=FFFFFF80,b=-128.

a=0000007F,b=-129.

补码的加、减法

  对一个二进制数按位求反、末位加一的运算称为求补运算,补码表示的数具有以下特征:

  补码的加法规则是:[X+Y]补=[X] 补+[Y] 补

  补码的减法规则是:[X-Y] 补=[X] 补+[-Y] 补

  其中通过对求补就可以得到。

  在机器里,补码减法是通过对减数求补后把减法转换为加法进行的。符号位参加运算,能自动得到正确结果。

  例:假设机器字长为8位,计算25+(-32)

    25的补码是0001 1001,-32的补码是1110 0000,

  结果恰好是-7的补码1111 1001,可以看出运算是正确的。

  例:仍假定机器字长为8位,计算32-(-25)

    为把减法转换为加法,要对-25求补,实际上就是25的补码0001 1001, 32的补码是0010 0000,

  结果恰好是57的补码0101 0111,运算正确。

  在某些情况下,要处理的数全是正数(比如表示地址的数),就没有必要保留符号位了,可以把最高有效位也作为数值处理,这样的数称为无符号数。n位无符号数的表数范围是。

第4节 BCD码

二进码十进数(英语:Binary-Coded Decimal,简称BCD,台湾称二进码十进数)是一种十进制的数字编码形式。这种编码下的每个十进制数字用一串单独的二进制位元来储存表示。常见的有4位元表示1个十进制数字,称为压缩的BCD码(compressed or packed);或者8位元表示1个十进制数字,称为未压缩的BCD码(uncompressed or zoned)。

这种编码技术,最常用于会计系统的设计里,因为会计制度经常需要对很长的数字串作准确的计算。相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免却使电脑作浮点运算时所耗费的时间。此外,对于其他需要高精确度的计算,BCD编码亦很常用。

BCD码的主要优点是在机器格式与人可读的格式之间转换容易,以及十进制数值的高精度表示。BCD码的主要缺点是增加了实现算术运算的电路的复杂度,以及存储效率低。

常用BCD编码方式

最常用的BCD编码,就是使用"0"至"9"这十个数值的二进码来表示。这种编码方式,称为8421BCD, 除此以外,对应不同需求,各人亦开发了不同的编码方法,以适应不同的需求。这些编码,大致可以分成有权码和无权码两种:

1.有权码,如:8421(最常用)、2421、5421…

2.无权码,如:余3码、格雷码…

1.8421BCD编码

  这是一种使用最广的BCD码,是一种有权码,其各位的权分别是(从最有效高位开始到最低有效位)8、4、2、1(即23、22、21、20),因而称为“8421BCD编码”。

比如:8421BCD码的1011=8*1+4*0+2*1+1*1=11

在使用8421BCD码时一定要注意其有效的编码仅十个,即:0000~1001。4位二进制数的其余6个编码1010、1011、1100、1101、1110、1111不是有效编码。这种BCD编码实际上就是0~9的“等值”二进制数。

2.2421BCD编码

  2421BCD码也是一种有权码,其从高位到低位的权分别为2、4、2、1(同样也是它得名的原因),其也可以用4位二进制数来表示1位十进制数。

比如: 2421BCD码的(1100 0100 0010)=十进制的(6 4 2)

因为

2421BCD码的1100=2*1+4*1+2*0+1*0=6

2421BCD码的0100=2*0+4*1+2*0+1*0=4

2421BCD码的0010=2*0+4*0+2*1+1*0=2

3.余3码

  余3码也是一种BCD码,但它是无权码。但由于每一个码对应的8421BCD码之间相差3,故称为余3码,其一般使用较少,故只须作一般性了解。

余三码是在8421BCD码的基础上,把每个数的代码加上0011(对应十进制数3)后得到的。

4.格雷码

格雷码(循环二进制单位距离码)是任意两个相邻数的代码只有一位二进制数不同的编码,它与奇偶校验码同属可靠性编码。

格雷码(Gray code)是由贝尔实验室的Frank Gray在1940年提出,用于在PCM(脉冲编码调变)方法传送讯号时防止出错,并于1953年3月17日取得美国专利。格雷码是一个数列集合,相邻两数间只有一个位元改变,为无权数码,且格雷码的顺序不是唯一的。

格雷码能避免讯号传送错误的原理

传统的二进位系统例如数字3的表示法为011,要切换为邻近的数字4,也就是100时,装置中的三个位元都得要转换,因此于未完全转换的过程时装置会经历短暂的,010,001,101,110,111等其中数种状态,也就是代表着2、1、5、6、7,因此此种数字编码方法于邻近数字转换时有比较大的误差可能范围。葛雷码的发明即是用来将误差之可能性缩减至最小,编码的方式定义为每个邻近数字都只相差一个位元,因此也称为最小差异码,可以使装置做数字步进时只更动最少的位元数以提高稳定性。 数字0~7的编码比较如下:

十进位 葛雷码 二进位

0     000    000

1     001    001

2     011    010

3     010    011

4     110    100

5     111    101

6     101    110

7     100    111

直接排列

以二进制为0值的格雷码为第0项,第1项改变最右边的位元,第2项改变右起第一个为1的位元的左边位元,第3、4项方法同第1、2项,如此反复,即可排列出n个位元的格雷码。

格雷码转二进位数

二进位码第n位 = 二进位码第(n+1)位+格雷码第n位。因为二进位码和格雷码皆有相同位数,所以二进位码可从最高位的左边位元取0,以进行计算。(注:遇到1+1时结果视为0)

例如: 格雷码0111,为4位数,所以其所转为之二进位码也必为4位数,因此可取转成之二进位码第五位为0,即0 b3 b2 b1 b0。

0+0=0,所以b3=0

0+1=1,所以b2=1

1+1=10取0,所以b1=0

0+1=1,所以b0=1

因此所转换为之二进位码为0101

应用

格雷氏编码与相位移在三维曲面量测:利用格雷码投射在微型曲面做量测 一个非接触式、投影的方法光学测量。在化简逻辑函数时,可以通过按格雷码排列的卡诺图来完成。

和葛雷码有相同数学模式的玩具

中国的古老益智玩具九连环有着和格雷码完全相同的数学模式,外国一款名为spin out的玩具也是运用相同的数学模式。

时间: 2024-09-29 03:03:17

字符编码--第2章 数的存储的相关文章

MySQL的字符编码体系(一)——数据存储编码

安装MySQL好多次了,每次都会纠结于数据库的字符编码配置,所以我决定这一次彻底把它理清. MySQL的字符编码结构比较细,它大方向分为两个部分:数据存储编码和数据传输编码.本篇讨论数据存储编码部分,数据传输编码在下一篇MySQL的字符编码体系(二)--数据传输编码中讨论. 编码层次 数据存储的字符编码配置是指定数据库中存储的数据默认采用什么字符编码.默认字符编码的设置分为四个层次:服务器级.数据库级.数据表级和列级.也就是说,可以为服务器设置一个默认字符编码,再为服务器中的每一个数据库设置不同

字符编码--第3章 字符的存储--ANSI编码

第11节 ANSI编码 为使计算机支持更多语言,通常使用 0x80~0xFF 范围的 2 个字节来表示 1 个字符.比如:汉字 '中' 在中文操作系统中,使用 [0xD6,0xD0] 这两个字节存储. 不同的国家和地区制定了不同的标准,由此产生了 GB2312.GBK.GB18030.Big5.Shift_JIS 等各自的编码标准.这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码.在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码:在繁体中文Windo

ASCII,Unicode,GBK和UTF-8字符编码的区别和联系

如果经常写python2,肯定会遇到各种"奇怪"的字符编码问题,每次都通过谷歌解决了,但是为什么会造成这种乱码.decode/encode失败等等,本文就字符和字符编码做一个总结,更加清晰区分诸多的编码. 字符集 一个系统支持的所有抽象字符的集合.字符是文字和符号的总称,包含各个国家文字.标点符号.图像符号.数字等.它为每一个字符分配一个唯一的ID,一般称之为码位.码点. 字符编码 它是一套规则,使用该规则能够将自然语言的字符的一个集合与其他东西的一个集合进行配对,在符号集合和数字系统

Python 2中万恶的字符编码

Python2中如果文件存在中文,必须要指定#-*- coding:utf8 -*-或#coding:utf8,否则会报错.那这是为什么呢? 我们知道,在计算机发展初期,计算机只能识别字母,数字和一些基本符号,其使用8位存储空间存储所有的内容,也就是2^8=256个不同的结果,这就是ASCII码.在当时的情况下,并没有想到日后其他语言文字的扩展,随着不断的发展,对计算机的使用越来越广泛,使用8位存储空间早已不能满足人们的日常需求,所以Unicode(万国码)就这样诞生了.顾名思义,Unicode

字符编码【转载】

转载:http://www.techug.com/character-encoding 字符集和字符编码 编程技术2015-3-26TECHUG2条评论 本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧. 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难.本文就将会从原理方面对字符集和编码做个简单的科普介绍,同时也会介绍一些通用的乱码故障定位的方法以方便读者以后能够更从容的定位相关问题.在正式介绍

十分钟搞清字符集和字符编码

本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧. 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难.本文就将会从原理方面对字符集和编码做个简单的科普介绍,同时也会介绍一些通用的乱码故障定位的方法以方便读者以后能够更从容的定位相关问题.在正式介绍之前,先做个小申明:如果你希望非常精确的理解各个名词的解释,那么可以查阅wikipedia.本文是博主通过自己理解消化后并转化成易懂浅显的表述后的介绍.

(转)十分钟搞清字符集和字符编码

十分钟搞清字符集和字符编码 转载自: http://cenalulu.github.io/linux/character-encoding/作者: 卢钧轶 本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难. 本文就将会从原理方面对字符集和编码做个简单的科普介绍,同时也会介绍一些通用的乱码故障定位的方法以方便读者以后能够更从容的定位相关问题. 在正式

搞清字符集和字符编码

本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难.本文就将会从原理方面对字符集和编码做个简单的科普介绍,同时也会介绍一些通用的乱码故障定位的方法以方便读者以后能够更从容的定位相关问题.在正式介绍之前,先做个小申明:如果你希望非常精确的理解各个名词的解释,那么可以查阅wikipedia.本文是博主通过自己理解消化后并转化成易懂浅显的表述后的介绍. 什

【转载】十分钟搞清字符集和字符编码

十分钟搞清字符集和字符编码 什么是字符集 什么是字符编码 UTF-8和Unicode的关系 UTF-8编码简介 为什么会出现乱码 如何识别乱码的本来想要表达的文字 常见问题处理之Emoji 本文将简述字符集,字符编码的概念.以及在遭遇乱码时的一些常用诊断技巧 背景:字符集和编码无疑是IT菜鸟甚至是各种大神的头痛问题.当遇到纷繁复杂的字符集,各种火星文和乱码时,问题的定位往往变得非常困难.本文就将会从原理方面对字符集和编码做个简单的科普介绍,同时也会介绍一些通用的乱码故障定位的方法以方便读者以后能