java int 乘法溢出问题
今天在看框架的工具包时发现了一个细节,
double d=1024d * 1024 * 1024 * 1024;
第一个1024后面为什么要带个d呢?
于是我尝试了一下:
double d = 1024d * 1024 * 1024 * 1024;
double dw = 1024 * 1024 * 1024 * 1024 ;
System.out.println(d);
System.out.println(dw);
结果为:
1.099511627776E12
0
--------------
0?为啥是0?? java的普通数字类型是int,1024是int,4个int的1024相乘(2^40)已经超出了int的表示范围了,2^32,
http://bbs.csdn.net/topics/40216116
看了《Java虚拟机说明书》中“Java语言编程概念”中对“基本数据类型的变窄转换”的介绍才算明白了。
对于
int i = 1000000;
System.out.println(i*i);
-----------------------
-727379968
-----------------------
的合理解释和过程应该是这样的:
i设置为1000000,在乘方时Java发现结果(1000000000000)已经超出了int基本数据类型的最大范围(2147483647),于是作了默认的类型提升(type promotion),中间结果做为long类型存放,返回结果时目标数据类型int不能够容纳下结果,于是根据Java的基础类型的变窄转换(Narrowing primitive conversion)规则,把结果宽于int类型宽度的部分全部丢弃,也就是只取结果的低32位,于是就得到了上面的结果。
下面用一个十六进制表示的例子阐释这个问题
int i3 = 1000000;
System.out.println (Long.toHexString (i3*i3).toUpperCase());
System.out.println (Long.toHexString (i3*i3).toUpperCase());
System.out.println (Integer.toHexString (i3*i3).toUpperCase());
System.out.println ((int)i3*i3);
---------------------------------------------------
FFFFFFFFD4A51000
1000000000000
D4A51000
-727379968
---------------------------------------------------
截取是非常直观的
原来如此,于是加了d的1024相乘,结果就会以double储存,这样才能得到正确的结果...真意外 啊啊啊.