16

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

 4 years ago
source link: https://www.tuicool.com/articles/vqeYjaf
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

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

fyAnErV.jpg!web

这时,小刘出现了!没错,就是那个大家期待的小刘出现了!她拿着一本《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 的源码是下面这样的

N7nIniN.jpg!web

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

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

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

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

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

rQRvay6.jpg!web

越界问题

烟哥说道:"这样吧,先问你一个问题。 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!"

An2QveQ.jpg!web

(本文完!)


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK