Java中一个普通的循环为何从10开始到99连续相乘会得到0?
这是一块非常简单的Java代码片段:
public class HelloWorld{
public static void main(String []args){
int product = 1;
for (int i = 10; i <= 99; i++) {
product *= i;
}
System.out.println(product);
}
}
为什么得出的结果是0呢?
问题现象
蛋疼的同学可能会发现这个程序执行的规律:
1 * 10 = 10
10 * 11 = 110
110 * 12 = 1320
1320 * 13 = 17160
17160 * 14 = 240240
240240 * 15 = 3603600
3603600 * 16 = 57657600
57657600 * 17 = 980179200
……
-1342177280 * 40 = -2147483648
-2147483648 * 41 = -2147483648
-2147483648 * 42 = 0
0 * 43 = 0
0 * 44 = 0
……
0 * 97 = 0
0 * 98 = 0
程序从42开始就已经输出0,所以42以后的数字相乘的结果就显而易见了。从结果中发现,乘积的符号已一种难以理解的方式变换着,表明乘积已经溢出了,同时也说明Java并不会理会整数的上下溢出。
问题解答
请记住Java的int类型是32位的有符号二进制补码表示的数字类型(译者注:64为jdk同样如此)。这是每一步乘法在计算机内部所做的操作:

标注(1)是实际十进制结果。
标注(2)十六进制以及十进制的内部表示结果,int类型只会存储低32位的数据。
标注(3)是标注(2)的补码形式。
如果你好奇0从哪里来,请仔细看上方2进制表示的结果。细心的同学会注意到:
任何一个数与偶数相乘得偶数。
偶数与偶数相乘,会将2进制位整体左移,0从右边填补空位。
偶数与奇数相乘,不会改变最右方0的数量。
当乘法执行的足够多次时,右方的0位会越来越多。最终,连续乘到42时,乘积的2进制表示的低32位全是0,所以int将会是0。
问题扩展
既然知道了问题的原因,我们换一种变量来做同样的操作,以byte为例。
Java的byte变量是8位的有符号数,同样也是补码表示。从上方结果表格看出,连续从10乘到16时,2进制结果的低8位全都是0,所以此时的byte变量是0。而连续乘到15时,低8位是10010000,还记得怎么由补码求原码吗?很简单, 符号位不变,其余位取反加1,得出11110000,既-112,感兴趣的朋友请在自己机器上验证结果。有兴趣的同学可以加入技术讨论群:626267345

Java中一个普通的循环为何从10开始到99连续相乘会得到0?的更多相关文章
- Java中的do-while循环——通过示例学习Java编程(11)
作者:CHAITANYA SINGH 来源:https://www.koofun.com/pro/kfpostsdetail?kfpostsid=22&cid=0 在上一篇教程中,我们讨论了w ...
- Java中的for循环——通过示例学习Java编程(9)
作者:CHAITANYA SINGH 来源:https://www.koofun.com/pro/kfpostsdetail?kfpostsid=21 循环用于反复执行同一组语句,直到满足特定条件 ...
- [转帖]java中的for循环
java中的for循环 https://baijiahao.baidu.com/s?id=1621622990642364099&wfr=spider&for=pc 发现自己连 for ...
- java中一个字符串是另外一个字符串的字串
java中一个字符串是另外一个字符串的字串 String类中有一个方法 public boolean contains(Sting s)就是用来判断当前字符串是否含有参数指定的字符串例s1=“take ...
- java中一个引人深思的匿名内部类
前两天去面试javaweb问到一个问题,在你的项目中有没有用到线程,我特么的一想,这东西不是在c层面的吗,所以说我不了解线程..... 后来回去想啊想啊,我操这特么的不是再问我事物的控制,消息队列的回 ...
- JAVA中的for-each循环与迭代
在学习java中的collection时注意到,collection层次的根接口Collection实现了Iterable<T>接口(位于java.lang包中),实现这个接口允许对象成为 ...
- JAVA中的for循环
在Java程序中,要“逐一处理”――或者说,“遍历”――某一个数组或Collection中的元素的时候,一般会使用一个for循环来实现(当 然,用其它种类的循环也不是不可以,只是不知道是因为for这个 ...
- Java中的break循环——通过示例学习Java编程(13)
作者:CHAITANYA SINGH 来源:https://www.koofun.com//pro/kfpostsdetail?kfpostsid=24 break语句通常用于以下两种情况: (A)使 ...
- Java中list在循环中删除元素的坑
JAVA中循环遍历list有三种方式for循环.增强for循环(也就是常说的foreach循环).iterator遍历. 1.for循环遍历list for(int i=0;i<list.siz ...
随机推荐
- 女生学Java编程是什么感受?
那我就代表女生来说说感受 在编程的世界很难遇到好看的帅哥 记得当年15年7月4号是我实习生入职的日子,因为是校企合作,所以没有面试.老师推荐.直接入职.刚来北京第一个感觉就是人多,还有就是热.刚到公司 ...
- PHP is_nan() 函数
实例 判断一个值是否为非数值: <?phpecho is_nan(200) . "<br>";echo is_nan(acos(1.01));?>高佣联盟 ...
- JavaScript Object的复制
var obj = { a: 1, b: 2, c: { d: 3, e: 4, f: function () { console.log("对象复制"); } } } 1. fo ...
- 4.24 省选模拟赛 欧珀瑞特 主席树 可持久化trie树
很容易的一道题目.大概.不过我空间计算失误MLE了 我草草的计算了一下没想到GG了. 关键的是 我学了一个dalao的空间回收的方法 但是弄巧成拙了. 题目没有明确指出 在任意时刻数组长度为有限制什么 ...
- MySQL的undo/redo日志和binlog日志,以及2PC
发现自己的知识点有点散,今天就把它们连接起来,好好总结一下. 一.undo log.redo log.binlog的定义和对比 定义和作用 所在架构层级 ...
- MB2-718 Certification: (Microsoft Dynamics 365 Customer Service) – Field Service, Customer Assets
Come from : https://neilparkhurst.com/2018/02/25/mb2-718-certification-microsoft-dynamics-365-custom ...
- 埋在MySQL数据库应用中的17个关键问题!
作者:扎瓦陈序元 来源:https://blog.csdn.net/weixin_42882439 MySQL的使用非常普遍,跟MySQL有关的话题也非常多,如性能优化.高可用性.强一致性.安全.备份 ...
- CSS漂亮盒子(下)
4.多重背景 CSS支持一个元素设置多个背景图片. 每个背景属性有相应的多值语法,多个值由逗号分隔. .multi-bg-shorthand { width: 300px; height: 200px ...
- Java 基础 —— 注解 Annotation
简介 Annotation 是从 JDK 5.0 引入的. 注解使得我们可以以编译器验证的格式存储程序的额外信息.注解可以生成描述符文件,甚至是新的类定义,并且有助于减轻编写"样板" ...
- 小白入门Web前端开发学习一周小结
说之前还是先说点其他的,简单介绍下自己为何选择web前端开发: 本人之前在一家国企单位从事质检工作,干了3年,工资和待遇还算不错,但由于其工作的流动性导致知识的脱轨以及精神上的空缺,最后还是打算在25 ...