数制转换及原码补码反码问题

数制转换及原码补码反码问题

标签(空格分隔): 面向对象技术与C++


转载http://blog.sina.com.cn/s/blog_9b60c8e00100y47j.htmlhttp://www.94cto.com/index/Article/content/id/59973.html
对文章进行整合和重新排版

进制转换

在计算机里,通常用数字后面紧跟一个英文字母来表示该数的数字,十进制一般用D,二进制用B,八进制用O,十六进用H来表示

十进制转二进制

首先,十进制数转换成二进制,除2取余,按箭头方向写,自上而下写出来,所以45D转换成二进制为:101101B

十进制转十六进制

十进制数转换成十六进除16取余,16进制一般用0~9,A,B,C,D,E,F,所以,117D转换成十六进制为:75H

十六进制转二进制

十六进制到二进制:每一位用4位二进制数来表示,最终形成对应的二进制数,如:

A19CH :A=10(十进制)=1010 ,1 = 0001 ,9 = 1001,C = 12(十进制)=1100,所以A19CH = 1010000110011100B

机器数

字,字长概念

通常,机器数是把符号”数字化”的数,是数字在计算机中的 二进制 表示形式。

字长:一般说来,计算机在同一时间内处理的一组二进制数称为一个计算机的“字”,而这组二进制数的位数就是“字长”。

字长与计算机的功能和用途有很大的关系,是计算机的一个重要技术指标。字长直接反映了一台计算机的计算精度,为适应不同的要求及协调运算精度和硬件造价间的关系,大多数计算机均支持变字长运算,即机内可实现半字长、全字长(或单字长)和双倍字长运算。在其他指标相同时,字长越大计算机的处理数据的速度就越快。早期的微机字长一般是8位和16位,386以及更高的处理器大多是32位。目前市面上的计算机的处理器大部分已达到64位。

数的符号数值化

实用的数据有正数和负数,由于计算机内部硬件只能表示两种物理状态(用0和1表示),因此实用数据的正号“+”或负号“-”,在机器里就用一位二进制的0或1来区别。通常这个符号放在二进制数的最高位,称符号位,以0代表符号“+”,以1代表符号“-”。因为有符号占据一位,数的形式值就不等于真正的数值,带符号位的机器数对应的数值称为机器数的真值。例如二进制真值数-011011,它的机器 1011011。

二进制的位数受机器设备的限制

机器内部设备一次能表示的二进制位数叫机器的字长,一台机器的字长是固定的。字长8位叫一个字节(Byte),现在机器字长一般都是字节的整数倍,如字长8位、16位、32位、64位。

机器码的表示方法

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

原码

将数的真值形式中“+”号用“0”表示,“-”号用“1”表示时,叫做数的原码形式,简称原码。若字长为n位,原码一般可表示为:

当X为正数时[X]原和X一样,即[X]原 = X。当X为负数时。由于X本身为负数,所以,实际上是将∣X∣数值部分绝对值前面的符号位上写成“1”即可。

原码表示法比较直观,它的数值部分就是该数的绝对值,而且与真值、十进制数的转换十分方便。但是它的加减法运算较复杂。当两数相加时,机器要首先判断两数的符号是否相同,如果相同则两数相加,若符号不同,则两数相减。在做减法前,还要判断两数绝对值的大小,然后用大数减去小数,最后再确定差的符号,换言之,用这样一种直接的形式进行加运算时,负数的符号位不能与其数值部分一道参加运算,而必须利用单独的线路确定和的符号位。要实现这些操作,电路就很复杂,这显然是不经济实用的。为了减少设备,解决机器内负数的符号位参加运算的问题,总是将减法运算变成加法运算,也就引进了反码和补码这两种机器数。

反码

如前所述,为了克服原码运算的缺点,采用机器数的反码和补码表示法。若字长为n位,反码可表示为:

即对正数来说,其反码和原码的形式相同;对负数来说,反码为其原码的数值部分各位变反。

补码

补码是根据同余的概念引入的,我们来看一个减法通过加法来实现的例子。假定现在是北京时间6点整,有一只手表却是8点整,比北京时间快了2小时,校准的方法有两种,一种是倒拨2小时,一种是正拨10小时。若规定倒拨是做减法,正拨是做加法,那么对手表来讲减2与加10是等价的,也就是说减2可以用加10来实现。这是因为8加10等于18,然而手表最大只能指示12,当大于12时12自然丢失,18减去12就只剩6了。这说明减法在一定条件下,是可以用加法来代替的。这里“12”称为“模”,10称为“-2”对模12的补数。推广到一般则有:
         A – B = A + ( – B + M ) = A + ( – B )补
总之,正数的原码、反码和补码是完全相同的;负数的原码、反码和补码其形式各不相同。另外,特别要注意的是,对于负数的反码和补码(即符号位为1的数),其符号位后边的几位数表示的并不是此数的数值。如果要想知道此数的大小,一定要求其反码或补码才行。

心算求补(大神求补算法)原码->补码:

从最低位开始至找到的第一个1均不变,符号位不变,这之间的各位“求反”(0变1;1变0)。
原码:1010 1001 补码:1101 0111.

多数机器里面都是采用补码表示,正数采用符号+绝对值表示,如:假设机器字长为8位,则[+1]补 = 00000001,[+127]补=01111111,[+0]补=00000000,当用补码表示法表示负数时,负数X用2的n次方-[X]来表示,其中n为机器的字长。如:[-1]补 = 28-1 = 11111111,[-127]补 = 28-127=256-127=129=1000001,0的补码就只有一种表示法:八个0,00000000.

对于10000000这个数,在补码表示法中被定义为-128,采用补码形式表示的有符号数,那么n位二进制数据能够表示的有符号整数的范围是:
              2n1 ~ 2n11
那么,8位表示的有符号数的范围是:-128~127,如果n =16,那么能够表示的有符号数整数的范围是-32768~32767(记住这个范围)

例如,假设机器字长是16位,写出-117D的补码表示:
-117D = 216-117D 我把每个数都转化成2进制,也就是1 0000 0000 0000 0000 – 0000 0000 0111 0101 = 1111 1111 1000 1011 这个数转换成六进制就是 FF8BH。
我采用书上的解法就是:

首先:+117D可表示为: 0000 0000 0111 0101
按位求反后为 1111 1111 1000 1010
某位加1 后: 1111 1111 1000 1011
表示成十六进制: FF8B(最终结果)

如果,对于无符号数来说,8位无符号数的表示范围: 0<=n<=2n1 ,即:0~255 ; 16位无符号数的表示范围: 0<=n<=2n1 ,即:0~65535(也要记住)

符号扩展

符号扩展,常需要把一个n位二进制数扩展为m位二进制数,(m>n),当要扩充的数十无符号数时,只要在最高位前扩展m-n个0,例如,21的8位二进制和16位二进制的补码表示如下:00010101 8位, 0000000000010101 16位

如果要扩展的数是有符号数,并且采用补码形式表示,进行符号扩展,如:-3的8位二进制补码和16位二进制补码如下:

真值-3
1111 1101 8位补码,
1111 1111 1111 1101 16位补码

有符号数与无符号数的相互转换

  • 无符号整数和有符号整数之间进行强制类型转换时,位模式不改变。
  • 有符号数转换为无符号数时,最高符号位失去位意义,变为数据位。负数转换为大的正数,相当于在原值上加上2的n次方,而正数保持不变。
void main(){
    int a = -1;
    unsigned int b;
    b = a;
    printf("%u",b);
}
结果:4294967295
计算过程:32位长度表示有符号整数a为0xFFFFFFFF,转化为无符号整数时,最高位变为数值位,所以转化为无符号整数后值为0xFFFFFFFF,为32位最大整数4294967295
  • 无符号数转换为有符号数时。对于小的数将保持原值,对于大的数将转换为负数,相当于原值减去2的n次方。
void main(){
    int a;
    unsigned int b = 4294967295;
    a = b;
    printf("%d",a);
}
结果:-1
计算过程:32位长度表示无符号整数b为0xFFFFFFFF,转化为有符号整数时,最高位变为数值位,所以转化为无符号整数后值为0xFFFFFFFF,为负数,其真值的大小为-1
  • 当表达式中存在有符号数和无符号数类型时,所有的操作都自动转换为无符号类型。可见无符号数的运算优先级高于有符号数。

转换大餐

有符号数的转换

原类型目标类型转换方法
 char

short

符号位扩展
charlong符号位扩展
charunsigned char最高符号位失去位意义,变为数据位
charunsigned short符号位扩展到short;然后从short转到unsigned short
charunsigned long符号位扩展到long;然后从long转换到unsigned long
charfloat符号位扩展到long;然后从long转到float
chardouble符号位扩展到long;然后从long转换到double
charlong double符号位扩展到long;然后从long转换到long double
shortchar保留低位字节(short a=0x1234; char b = a;则b=0x34)
shortlong符号位扩展
shortunsigned char保留低位字节
shortunsigned short

最高为失去意义,变为数据位

shortunsigned long符号位扩展到long;然后从long转到unsigned long
shortfloat符号位扩展到long;然后从long转到float
shortdouble符号位扩展到long;然后从long转到double
shortlong double符号位扩展到long;然后从long转换到long double
longchar保留低位字节
longshort保留低位字节
longunsigned char保留低位字节
longunsigned short保留低位字节
longunsigned long最高为失去意义,变为数据位
longfloat使用单精度浮点数表示,可能失去精度
longdouble使用单精度浮点数表示,可能失去精度
longlong double使用单精度浮点数表示,可能失去精度

无符号数的转换

原类型目标类型转换方法
unsigned charchar最高为作符号位
unsigned charshort0扩展
unsigned charlong0扩展
unsigned charunsigned short0扩展
unsigned charunsigned long0扩展
unsigned charfloat转换到long;然后从long转换到float
unsigned chardouble转换到long;然后从long转换到double
unsigned charlong double转换到long;然后从long转换到long double
unsigned shortchar保留低位字节
unsigned shortshort最高为作符号位
unsigned shortlong0扩展
unsigned shortunsigned char保留低位字节
unsigned shortunsigned long0扩展
unsigned shortfloat转换到long;然后从long转换到float
unsigned shortdouble转换到long;然后从long转换到double
unsigned longlong double转换到long;然后从long转换到long double
unsigned longchar保留低位字节
unsigned longshort保留低位字节
unsigned longlong最高位作符号位
unsigned longunsigned char保留低位字节
unsigned longunsigned short保留低位字节
unsigned longfloat转换到long;然后从long转换到float
unsigned longdouble直接转换到double
unsigned longlong double转换到long;然后从long转换到long double

补码的加法和减法

例如:用8位二进制计算,25+(-32)
我们用求补码的方式来解决这个问题,25是整数,他的补码为:00011001,(-32)的补码是:先求32的补码:00100000,对它求反:11011111,末尾加1,得:11100000,然后把它与25的补码00011001相加得11111001,这个数最高位为1,肯定是个负数,我们对这个数求反再末尾加1,得00000111,刚好为7,所以11111001就是-7,跟我们用十进制算出来的结果一样。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值