杂货边角(1):计算机中有符号数和浮点数表示和运算

1. 整数的有符号表示方式

计算机中目前常用的整数类型分为 int_32int_64,以32位为例。计算机中都以补码形式存放有符号数。

正整数的补码表示和正整数的无符号类型一致,符号位为0;
负整数的补码表示则需要依次经过求反码,求补码,举例如下

对于-4而言,则符号位为1, 4的二进制表示为 000 0000 0000 0100
求反码:                             111 1111 1111 1011
求补码(反码-1):                     111 1111 1111 1010
则最终-4在计算机中补码形式为:          1111 1111  1111 1010 (0xFFFA)

很多程序语言并没有无符号数,在实际编程中很少用到有符号数,C语言是支持无符号数的,但是不恰当的使用无符号数会导致一些很危险的操作,当一个有符号数和一个无符号数运算时,有符号数会被转换成无符号数的形式(隐式转换)。所以除非在特别确定的场景下(如计数器),否则尽量不要为了省点空间而采用unsigned这种炫技前缀。

2. 浮点数的有符号表示方式

相信很多关于浮点数的网上资料都是IEEE 754的拷贝,把本来很简单的东西说的很复杂,其实就是一张图的问题
这里写图片描述
再额外举一个例子,两相对比,将会对浮点数的精度不定和截断误差有更深的理解。

浮点数:4.025675
整数部分40010 ; 小数部分:.0000 0110 1001 0010 1010 01  
第一次整合:10. 0000 0110 1001 0010 1010 01 可以发现小数点要向左移动1位才能到符号位1之后
则E = 127 + 1 = 128,即E1000 0000
符号位为0,代表正数
最终表示为:0 1000 0000 .0000 0011 0100 1001 0101 001
即对应十六进制0x4001A4A9

从上面可以看到浮点数由于存在着移位偏移的原因,故而导致浮点数的最小精度是不定的,这也浮点数存在截断误差的原因所在。可以看到浮点数的存储格式和整数的存储格式不同,这也是为何整数和浮点数做运算必须先将整数转换为浮点数,而整数转换为浮点数很简单,因为整数是浮点数的一个特例,即小数部分为0。

2. 有符号整数的运算方式

加法
有符号整数的加法其实很简单,即两个有符号整数的补码相加(符号位也是要正常进位),然后计算结果作为正常有符号整数进行解析,举两个例子

-3 + -2
出于简单起见,数据内容设置为4位,符号位设置在第5位,则-3: 1 1101; -2: 1 1110
1 1101 + 1 1110 = 11 1011截断为1 1011,解析为-5 
-4 + 8
出于简单起见,数据内容设置为4位,符号位设置在第5位,则8: 0 1000; -4: 1 1100
则0 1000 + 1 1100 = 10 0100截断为0 0100即为4

减法
从上面 -4+8可以看到,先将减数转换为补元,然后再和被减数相加即可。即可将有符号整数的减法转换为加法。

8 - 4
出于简单起见,数据内容设置为4位,符号位设置在第5位,则4的补元为2^4-4 = 12即1100,同时符号位取反,即为1
则得到4的补元为:1 1100,其实即为-4,这样便可以转换成下面的加法

-4 + 8
出于简单起见,数据内容设置为4位,符号位设置在第5位,则8: 0 1000; -4: 1 1100
则0 1000 + 1 1100 = 10 0100截断为0 0100即为4

乘法
其实乘除运算归根结底还是移位运算+加法运算的结合,其实原理和我们10进制乘法移位叠加并无本质区别。有符号整数的乘法一般是借助硬件加法器完成的,有补码一位乘法、两位乘法和三位乘法,位数越多,则计算速度越快,但对辅助的寄存器要求也越高。乘法的器的设计也是满精巧的,不过一般而言并无太多必要去了解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值