JAVA中令人眼花撩乱的数字魔法

栏目: Java · 发布时间: 5年前

五月的深圳空气中弥漫起初夏的味道,淡淡的,暖暖的。春日里不太张扬的阳光也掺入这股气息… (烟 哥好文采!)

这天,烟哥愉快的喝着霸气芝士莓莓莓。一边东张西望,寻找着可以装13的机会。一切正如下面这张图这样

JAVA中令人眼花撩乱的数字魔法

这时,小刘出现了!没错,就是那个大家期待的小刘出现了!她拿着一本《XXXjava笔试指南》来找烟哥。

只见小刘娴熟的打开这本书,望着整本书满满的笔记,烟哥不禁猜测道:"小刘如此热衷于学习,一定还是单身。"

想到这里,烟哥不禁更有回答的动力了 (没

错,我就是这种人!)

缓存问题

小刘翻到某一页后,指出下面这样一道题

public static void main(String[] args){
 Integer a = 50;
 Integer b = 50;
 Integer c = 150;
 Integer d = 150;
 System.out.println(a==b);
 System.out.println(c==d);
}

输出结果为

true
false

然后询问烟哥具体缘由。

烟哥看完以后,内心 正(wei)直(suo) 的笑了笑,心里想道:"这不是几年前的老题目了么,怎么现在还在考!"

烟哥回答道:"其实很简单,原理是下面这样滴!"

JAVA编译器编译Integer a = 50的时候,被翻译成

Integer a = Integer.valueOf(50);

valueOf 的源码是下面这样的

JAVA中令人眼花撩乱的数字魔法

看到了嘛,Integer内部有一个 IntegerCache 缓存。对于值范围在-128到127之间的数,会进行缓存。因此a和b范围在-128到127之间,所以指向的是同一个对象,所以判断结果是 true 。而c和d在128之外,所以每次都是返回一个新对象,所以判断结果是 false

听到这里,小刘似乎很满意的准备打道回府。

"不行,怎么能这样让小刘离开。我得多和小刘说说话!"

于是,烟哥说道:"小刘啊,其实 java 笔试里关于数值方面的陷阱,可以玩出很多花样,你了解多少?"

很自然的,小刘的表情是下面这样的

JAVA中令人眼花撩乱的数字魔法

越界问题

烟哥说道:"这样吧,先问你一个问题。 Math.abs(Integer.MIN_VALUE)) 的结果是正数还是负数?"

小刘:" Math.abs 是绝对值运算,结果应该是正数吧。"

烟哥:"不对,还是负数。Integer的范围为-2147483648~2147483647。不过我们先来看一眼 abs 函数的源码,如下所示"

public static int abs(int a) {
    return (a < 0) ? -a : a;
}

烟哥:"看了源码,其实很明显,绝对值运算的原理是判断这个数是否大于零,如果小于零则取负值。OK,回到我们题目。"

Integer.MIN_VALUE ,它的十六进制表示是 0x80000000。其符号位为1,其余所有的位都是0。取负数(反码+1)则为 0x7fffffff+1,也就是 0x80000000。你会发现对 Integer.MIN_VALUE 取负值还是本身。因此,结果还是负数。

小刘:"那你这套理论对 LongShortByte 都成立么?"

烟哥:"是的,都是成立的,原理都一样。你可以回去测试一下如下代码"

Short num =(short)Math.abs(Short.MIN_VALUE));
System.out.println(num);

小刘望着这些代码,陷入了思考…

突然,小刘回答道:"好像,之前我有看到一个题目是这样的。是否存在一个数i,可以使其满足 i+1<i ,这样看来,这个i就是 Integer.MAX_VALUE ,因为加完1就溢出了变为负值了。"

听小刘说道这里,烟哥换了一个角度问:"是否存在一个数,满足 i != 0 && i == -i "

小刘想了下,机智的回答道:"其实还是 Integer.MIN_VALUE ,原因你刚才说过了!"

唉,没想到小刘领悟如此的快!

浮点奥秘

烟哥感慨小刘领悟速度的同时,加大难度问道:"是否存在一个数,满足 i==i+1 ?"

小刘突然懵了,答道:"好像..似乎..应该一个数永远不会等于自己加一。"

看见小刘懵圈的眼神,烟哥只见自己装13的目的已经达到,便不再卖关子…

烟哥回答道:"有没听过一句话,无穷大加一个常数还是无穷大!所以,下面的例子输出为 true "

double i = Double.POSITIVE_INFINITY;
System.out.println(i == i+1);

小刘反怼烟哥,说道:"其实,无穷大减去一个常数也是无穷大。所以下面例子也是输出为 true ,而且无穷小也有类似的特性。"

double i = Double.POSITIVE_INFINITY;
System.out.println(i == i-1);

烟哥满意的点了点头,感慨小刘成长真快!

突然,灵光一闪,烟哥补充道:"你知不知道有一个数可以满足 i!=i ?"

小刘再次陷入了深思…嘴里嘟囔道:"奇怪,还有一个数可以自己不等于自己么?"

望着小刘愁眉苦脸的眼神 ,烟哥答道:"对,有一个不是数值的值,它就是 NaN ,翻译过来就是(Not a Number),因此下面的输出是为 true !"

double i = Double.NaN;
System.out.println(i != i);

结局

在烟哥一阵装13后,决定暴露自己的本性。问道:"小刘,你有对象了么?"

小刘答道:"烟哥,你是个好人,然而我已经有对象了!"

"Boom!"

JAVA中令人眼花撩乱的数字魔法

(本文完!)


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C++编程思想(第1卷)

C++编程思想(第1卷)

[美] Bruce Eckel / 刘宗田、袁兆山、潘秋菱 / 机械工业出版社 / 2002-9 / 59.00元

《C++编程思考》第2版与第1版相比,在章节安排上有以下改变。增加了两章:“对象的创建与使用”和“C++中的C”,前者与“对象导言”实际上是第1版“对象的演化”一章的彻底重写,增加了近几年面向对象方法和编程方法的最瓣研究与实践的有效成果,后者的添加使不熟悉C的读者可以直接使用这本书。删去了四章:“输入输出流介绍”、“多重继承”、“异常处理”和“运行时类型识别”,删去的内容属于C++中较复杂的主题,......一起来看看 《C++编程思想(第1卷)》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具