`

Java中负数以及类型转换问题

阅读更多
学习过java的都知道,在java中,不是直观的表示负数,而是采用补码的形式表示负数。这是为了硬件操作的方便,把减法也转换成加法来运算。

那补码是怎样表示的呢?为了得到补码,我们引入了反码。对于正数来讲,它的反码补码都为本身,如果不明白为什么,我们可以这样理解:引入反码补码的原因就是为了解决减法的问题,换句话数就是解决java中负数的问题,正数不存在这些问题,所以它的反码补码就是它本身。在有符号的基本数据类型中,最高位0表示正数,最高位1表示负数。 对于负数来讲,它的反码就是除去符号位取反,然后加1就得到了它的补码。

这里举个简单的例子,一个byte型数据,它在计算机中占8位,-7可以表示为10000111,最高位的1代表负号,它的反码是除去符号位各位取反为11111000,然后加1得到补码11111001。8的二进制表示为00001000,现在我们运算8 - 7,在计算机并不是用8减去7,而是用8 + (-7),也就是用00001000加上-7的补码11111001,两个有符号数相加,如果符号位相加有近位就删去符号位的进位,得到00000001,也就是1.

java中我们经常也会遇到不同数据类型的转换,这是最容易出错的地方。首先我们了解一下什么是符号扩展,对于正数来讲,在前面补0; 负数时在前面补1。比如8位的二进制数10000111扩展为16位,我们在前面加上8个1,1111111110000111;如果是正数,则在前面补0。这样进行扩展后,符号和数值的大小都不变。

接下来我们我们看一下不同类型之间是怎样转换的,首先我们要知道这些基本类型各自占几位。
有符号型:
byte = 8
int = 32
short = 16
long = 64
float = 32
double = 64
*boolean 只占一位,用0和1代表false和true。

无符号型:
char =  16

1. byte型转为char型
因为byte是有符号类型,再转成char型时需要进行符号位扩展,如果是正数就在前面不上8个0, 如果是负数就在前面补上8个1。例如11111111(0xff)左边连续补上8个1结果是0xffff。因为char是无符号类型,所以0xffff表示的十进制数是65535。

2. char型转为int型
因为char是无符号类型,转换成int型时进行在前面补上16个0,用十进制表示结果为结果0x0000ffff,对应的十进制数是65535。

3. int型转为byte型
因为int是32位,而byte类型值只占8位,直接截取最后8位。例如-1的补码为0xffffffff,转换为byte型后为0xff,值为-1。

总结:如果最初的数值类型是有符号的,那么就执行符号扩展;如果是char类型,那么不管它要被转换成什么类型,都执行零扩展。还有另外一条规则也需要记住,如果目标类型的长度小于源类型的长度,则直接截取目标类型的长度。例如将int型转换成byte型,直接截取int型的右边8位。

参考引用:
Joshua Bloch, 陈昊鹏译 - 《Java解惑》


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics