本文主要是介绍杂货边角(1):计算机中有符号数和浮点数表示和运算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
计算机中目前常用的整数类型分为
int_32
和
int_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
这种炫技前缀。
相信很多关于浮点数的网上资料都是IEEE 754的拷贝,把本来很简单的东西说的很复杂,其实就是一张图的问题
再额外举一个例子,两相对比,将会对浮点数的精度不定和截断误差有更深的理解。
浮点数:4.025675
整数部分4: 0010 ; 小数部分:.0000 0110 1001 0010 1010 01
第一次整合:10. 0000 0110 1001 0010 1010 01 可以发现小数点要向左移动1位才能到符号位1之后
则E = 127 + 1 = 128,即E: 1000 0000
符号位为0,代表正数
最终表示为:0 1000 0000 .0000 0011 0100 1001 0101 001
即对应十六进制0x4001A4A9
从上面可以看到浮点数由于存在着移位偏移的原因,故而导致浮点数的最小精度是不定的,这也浮点数存在截断误差的原因所在。可以看到浮点数的存储格式和整数的存储格式不同,这也是为何整数和浮点数做运算必须先将整数转换为浮点数,而整数转换为浮点数很简单,因为整数是浮点数的一个特例,即小数部分为0。
加法
有符号整数的加法其实很简单,即两个有符号整数的补码相加(符号位也是要正常进位),然后计算结果作为正常有符号整数进行解析,举两个例子
-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进制乘法移位叠加并无本质区别。有符号整数的乘法一般是借助硬件加法器完成的,有补码一位乘法、两位乘法和三位乘法,位数越多,则计算速度越快,但对辅助的寄存器要求也越高。乘法的器的设计也是满精巧的,不过一般而言并无太多必要去了解。
这篇关于杂货边角(1):计算机中有符号数和浮点数表示和运算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!