你的位置:首页 > Java教程

[Java教程]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位。 下载地址 ​