Java中整数溢出的问题:int i=1000000;i*i为何等于-727379968,Java是如何处理溢出的?

来源:互联网 发布:lns是什么社交软件 编辑:程序博客网 时间:2024/03/29 22:58

原提问地址:http://bbs.csdn.net/topics/40216116
问题:
读Java语言说明书到34页的时候碰到了一个整数相乘溢出的问题,百思不得其解,诚请行家指点。

int i=1000000;i*i为何等于-727379968?

书中说乘法是安装32位精度计算的。-727379968是计算结果1000000000000的低32位的十进制表示,计算结果对int类型来说太大了。怕英文水平有限个人理解有误,将原文附在下面(The multiplication is performed in 32-bit precision, The value -727379968 is the decimal value of the low 32 bits of the mathematical result, 1000000000000, which is a value too large for type int.)
问题如下:
1、Java是如何处理整数相乘溢出的?
2、i*i的低32位是如何取值法?我后来用i*i>>32得到了-727379968。
3、对于溢出是否先类型提升运算后再考虑精度问题?

答案

看了《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

截取是非常直观的

0 0
原创粉丝点击