首页 > 代码库 > 【java解惑】十六进制加法问题
【java解惑】十六进制加法问题
如下代码:
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解惑】十六进制加法问题