java解惑--谜题5:十六进制的趣事
来源:互联网 发布:怎么开企业淘宝店铺 编辑:程序博客网 时间:2024/05/18 03:53
谜题5:十六进制的趣事
摘自《java解惑》一书,下载地址:http://download.csdn.net/detail/itismelzp/9407769
下面的程序是对两个十六进制(hex)字面常量进行相加,然后打印出十六进制的结果。这个程序会打印出什么呢?
public class JoyOfHex{public static void main(String[] args){System.out.println( Long.toHexString(0x100000000L + 0xcafebabe));}}
看起来很明显,该程序应该打印出1cafebabe。毕竟,这确实就是十六进制数字10000000016 与cafebabe16 的和。该程序使用的是long 型运算,它可以支持16位十六进制数,因此运算溢出是不可能的。
然而,如果你运行该程序,你就会发现它打印出来的是cafebabe,并没有任何前导的1。这个输出表示的是正确结果的低32 位,但是不知何故,第33 位丢失了。看起来程序好像执行的是int 型运算而不是long 型运算,或者是忘了加第一个操作数。这里到底发生了什么呢?
十进制字面常量具有一个很好的属性,即所有的十进制字面常量都是正的,而十六进制或是八进制字面常量并不具备这个属性。要想书写一个负的十进制常量,可以使用一元取反操作符(-)连接一个十进制字面常量。以这种方式,你可以用十进制来书写任何int 或long 型的数值,不管它是正的还是负的,并且负的十进制常数可以很明确地用一个减号符号来标识。但是十六进制和八进制字面常量并不是这么回事,它们可以具有正的以及负的数值。如果十六进制和八进制字面常量的最高位被置位了,那么它们就是负数。在这个程序中,数字0xcafebabe是一个int 常量,它的最高位被置位了,所以它是一个负数。它等于十进制数值-889275714。
型数值相加。因为int 是一个有符号的整数类型,所以这个转换执行的是符合扩展:它将负的int 类型的数值提升为一个在数值上相等的long 类型数值。
这个加法的右操作数0xcafebabe 被提升为了long 类型的数值0xffffffffcafebabeL。这个数值之后被加到了左操作数0x100000000L 上。当作为int 类型来被审视时,经过符号扩展之后的右操作数的高32 位是-1,而左操作数的高32 位是1,将这两个数值相加就得到了0,这也就解释了为什么在程序输出中前导1 丢失了。下面所示是用手写的加法实现。(在加法上面的数字是进位。)
11111110xffffffffcafebabeL+ 0x0000000100000000L---------------------0x00000000cafebabeL
订正该程序非常简单,只需用一个long 十六进制字面常量来表示右操作数即可。这就可以避免了具有破坏力的符号扩展,并且程序也就可以打印出我们所期望的结果1cafebabe:
public class JoyOfHex{public static void main(String[] args){System.out.println(Long.toHexString(0x100000000L + 0xcafebabeL));}}
这个谜题给我们的教训是:混合类型的计算可能会产生混淆,尤其是十六进制和八进制字面常量无需显式的减号符号就可以表示负的数值。为了避免这种窘境,通常最好是避免混合类型的计算。对于语言的设计者们来说,应该考虑支持无符号的整数类型,从而根除符号扩展的可能性。可能会有这样的争辩:负的十六进制和八进制字面常量应该被禁用,但是这可能会挫伤程序员,他们经常使用十六进制字面常量来表示那些符号没有任何重要含义的
- java解惑--谜题5:十六进制的趣事
- 谜题5:十六进制的趣事
- Java谜题1-5十六进制趣事
- 《Java解惑》系列——01表达式之谜——谜题05:十六进制趣事
- java表达式问题 十六进制的趣事
- 十六进制的趣事
- 5.十六进制的趣事
- 【java解惑】十六进制加法问题
- java的一点趣事
- java小丑的毕业设计趣事
- Java浮点数的趣事
- java谜题4:16进制的趣事
- java解惑--谜题11:最后的笑声
- JAVA String的那点趣事
- 关于java中parseInt的一个趣事
- Java解惑5-类谜题
- java解惑 - 最后的笑声
- java解惑--灰色的影子
- 《算法竞赛入门经典2ndEdition 》习题3-6 纵横字谜的答案(Crossword Answers, Uva232)
- 数组和字符串
- Implement Trie Tree by hashmap
- 黑马程序员——OC之NSArray、NSDictionary
- Matlab 2012b--64bit安装教程
- java解惑--谜题5:十六进制的趣事
- BZOJ 1954 (POJ 3764) Trie的经典应用 求树上最大异或值
- 使用 DownloadManager 实现完全在后台下载
- CSU 1550-Simple String(字符串)
- A+B=X
- ThinkPHP中initialize和construct的不同
- style/Theme.NoTitleBar崩溃
- sql语句
- Codeforces Round #335 (Div. 2) A. Magic Spheres 水题