码迷,mamicode.com
首页 > 编程语言 > 详细

【java解惑】十六进制加法问题

时间:2014-12-21 02:03:36      阅读:598      评论:0      收藏:0      [点我收藏+]

标签:十六进制 补码 符号扩展


    如下代码:

public class Example005 {
	public static void main(String[] args) {
		System.out.println("out1="
				+ Long.toHexString(0x100000000L + 0xcafebabe));
		System.out.println("out2="
				+ Long.toHexString(0x100000000L + 0xcafebabeL));
	}
}


    输出结果:

out1=cafebabe
out2=1cafebabe


    原因分析:

    首先要知道的一个问题是,十进制数是依靠前导一元操作符(+/-)来表达正负的。而十六进制、八进制、二进制在计算机中是用补码表示的。补码的优势在于:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。在上述程序中,数字 0xcafebabe是一个 int 常量,它的最高位被置位了 ,所以它是一个负数。它等于十进制数值-889275714。

    out1执行的这个加法是一种混合类型的计算(mixed-type computation):左操作数是 long 类型的,而右操作数是 int 类型的。为了执行该计算,Java 将int 类型的数值用拓宽原始类型转换提升为一个 long 类型,然后对两个 long 类型数值相加。因为 int 是一个有符号的整数类型,所以这个转换执行的是符合扩展:它将负的 int 类型的数值提升为一个在数值上相等的 long 类型数值。这个加法的右操作数0xcafebabe 被提升为了 long 类型的数值0xffffffffcafebabeL。这个数值之后被加到了左操作数 0x100000000L 上。当作为 int 类型来被审视时, 经过符号扩展之后的右操作数的高 32 位是-1,而左操作数的高 32 位是 1,将这两个数值相加就得到了 0,这也就解释了为什么在out1的前导 1 丢失了。

    在out2中,0xcafebabeL使用十六进制字面常亮来表示,避免了有破坏力的符号扩展,所以打印结果也就正确了。



本文出自 “winger” 博客,谢绝转载!

【java解惑】十六进制加法问题

标签:十六进制 补码 符号扩展

原文地址:http://imu2008.blog.51cto.com/3844842/1592053

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!