C++ primer 查漏补缺二 :无符号数

自动类型转换:
当算数表达式中, 既有int又有无符号类型时,int会直接转换成无符号类型

数据在计算机中的存储

参考 机器数、真值、原码、反码和补码、大端方式 and 小端方式(数据的存储方式)
计算机中的数都是一串 0 1

无符号

无符号数它没有正负之分。

计算机中无符号数没有原码、反码和补码。因为,无符号数在计算机中直接将数字化成二进制然后存储在对应的存储器或者寄存器中。 这时寄存器或者存储器的位数就可以表示数值的范围,通常情况下一个数占一个字节,8位二进制,则这8位二进制都可以表示数字的取值, 所以它的取值范围是0-255,其中最小的值是0000 0000 ;最大的取值范围是1111 1111,表示的范围为 0 ~ 255。它的原码、反码和补码是一样的。

有符号

有符号的数, 符号数存储时不仅要将数据部分存入计算机, 还要将符号存进去。

有符号数,它的数分为正数、负数和0,在计算机中用一个字节中的最高位代表符号位,其中“0”表示正号,“1”表示符号,如-1,在计算机中表示1000 0001;1,在计算机中的表示为0000 0001;

正数的原码、反码和补码相同;负数的原码、反码和补码不同。

原码、补码、反码

我们人脑可以很轻松的知道机器数的第一位是符号位,但对于计算机基础电路设计来说判别第一位是符号位是非常难和复杂的事情,为了让计算机底层设计更加简单,人们开始探索将符号位参与运算,并且采用只保留加法的方法,我们知道减去一个数,等于加上这个数的负数,即:1-1 = 1 + (-1) = 0,这样让计算机运算就更加简单了,并且也让符号位参与到运算中去。

机器数:一个数在计算机的存储形式是二进制数,我们称这些二进制数为机器数,机器数是有符号,在计算机中用机器数的最高位存放符号位,0表示正数,1表示负数。

机器数的真值:因为带有符号位,所以机器数的形式值不等于其真值,以机器数1000 0111为例,其真正表示的值为-7,而形式值为135。将带符号的机器数的真正表示的值称为机器数的真值。

原码

原码的表示与机器数真值表示的一样,即用第一位表示符号,其余位表示数值,例如的十进制的的正负1,用8位二进制的原码表示如下:

【+1】= 原:[ 0000 0001 ]

【-1】= 原:[ 1000 0001 ]

使用原码运算

计算十进制表达式:1-1 = 0;

1 - 1 = 1 + (-1)

= 原:[ 0000 0001 ] + 原:[ 1000 0001 ]

= 原:[ 1000 0010 ] = -2

如果用原码表示,让符号位也参与计算,对于减法来说,结果是不正确的。这也是计算机内部在存储数据时不使用原码的原因,为了解决这一问题,出现了反码。

反码

反码的表示方法为:

正数的反码是其原码本身。
负数的反码是在其原码的基础上,符号位不变,其余各位取反。
【+1】= 原: [ 0000 0001 ] = 反:[ 0000 0001 ]

【-1】 = 原:[ 1000 0001 ] = 反:[ 1111 1110 ]

计算十进制表达式:1-1 = 0

1 - 1 = 1 + (-1)

= 原:[ 0000 0001 ] + 原:[ 1000 0001 ]

= 反:[ 0000 0001 ] + 反:[ 1111 1110 ]

= 反:[ 1111 1111 ] = 原: [ 1000 0000 ] = -0

结果的真值部分是正确的。而唯一的问题出现在"0"这个特殊的数值上,虽然人们理解上**+0和-0**是一样的,但是0带符号是没有任何意义的,而且会有[0000 0000]原和[1000 0000]原两个编码表示0。为了解决这一问题,出现了补码。

补码

正数的补码是其原码本身。
负数的补码是在其原码的基础上,符号位不变,其余各位取反后加1(即在反码的基础上加1)。

使用补码运算
【+1】= 原: [ 0000 0001 ] = 反:[ 0000 0001 ] = 补:[ 0000 0001 ]

【-1】 = 原:[ 1000 0001 ] = 反:[ 1111 1110 ] = 补:[ 1111 1111 ]

1 - 1 = 1 + (-1)

= 原:[ 0000 0001 ] + 原:[ 1000 0001 ]

= 补:[ 0000 0001 ] + 补:[ 1111 1111 ]

= 补: [ 0000 0000 ] = 原: [ 0000 0000 ] = 0

这样0用[0000 0000]表示,而以前出现问题的-0则不存在了,而且人们还发现可以用[1000 0000]表示-128,-128的推算过程如下:

(-1) + (-127) = -128

= 原:[1000 0001] + 原:[ 1111 1111 ]

= 补:[ 1111 1111 ] + 补:[ 1000 0001 ]

= 补:[ 1000 0000 ]

注意:因为实际上是使用以前的-0的补码来表示-128,所以-128并没有原码和反码表示,只要补码是[1000 0000],其十进制数值就为-128。

因为补码能多存储一个-128,而且在计算机底层中存储的是补码,所以在计算机中一个8位的二进制数的存储范围是用补码表示的[-128,127],而不是用原码或反码表示的[-127,127]。这也可以解释为什么计算机中一个字节的取值范围是[-128,127]。

总结
原码、反码、补码的使用,是人们为了让符号位能参与运算并让计算机底层运算更加简单而设计出来的数据存储表示方式。

有符号和无符号都是针对二进制数来讲的,并且他们都是以补码的方式在计算机中存储的。
有符号数:用最高位最符号位,‘0’代表正数,‘1’代表负数,其余位用作数字位代表数值位。
无符号数:所有位都为数值位,无正负之分,亦无符号位。

自动类型转换

当有符号数(int)和无符号数(unsignedint)进行算数运算时,有符号数(int)会先转换为无符号数(unsignedint),再进行相应的算数运算。

有/无符号整型数据的转换:

有->无:1)如果无的最高位是1,取补码;2)如果无的最高位是0,直接保存。

取补码:1)是正数的话,是其本身;2)是负数的话,符号位不变,其余各位取反,最后一位加1。

转换:

(1)无符号整数转换为有符号整数 :

看无符号数的最高位是否为1,如果不为1(为0),则有符号数就直接等于无符号数;如果无符号数的最高位为1,则将无符号数取补码,得到的数就是有符号数。
无符号数 a=255,首位为1,表示负数,其余为按位取反,
单字节表示:1111 1111
按位取反 :1000 0000
加1得 :1000 0001
得到-1;所以无符号数255转换为符号数为-1。

(2)有符号整数转换为无符号整数:

看有符号数的最高位是否为1,如果不为1(为0),则无符号数就直接等于有符号数;如果有符号数的最高位为1,则将有符号数取补码,得到的数就是无符号数。
将符号数-1转换为无符号数过程如下:
1000 0001
1111 1110
1111 1111
最终结果可得-1转换为无符号数255。

二进制数的原码,反码,补码,以及0的补码,有符号数,无符号数
负数的二进制表示及有符号数与无符号数之间的转换

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值