关于Schildt《Java入门指南》第二章自测质数程序的两大疑问
嘿,我来帮你把这两个问题掰扯清楚,搞明白质数判断里这些循环条件的门道~
1. j <= i/j 是质数查找的优化算法吗?
没错,这是一种优化过的质数判断逻辑,本质上等价于判断j <= Math.sqrt(i),但用除法的写法更稳妥。
质数的定义是:大于1的自然数,除了1和它本身之外没有其他正因数。那判断一个数i是不是质数,其实不需要检查从2到i-1的所有数——因为如果i有一个大于√i的因数,那必然存在一个对应的小于√i的因数(比如i=15,√15≈3.87,它的因数3和5,5>3.87,但3<3.87)。所以只要检查到√i就足够确定i是不是质数了,这样能大幅减少循环次数,提升效率。
而用j <= i/j而不是j <= Math.sqrt(i),是为了避免浮点运算的精度问题:比如当i是很大的整数时,Math.sqrt(i)可能因为浮点精度误差得到一个略小于实际平方根的数,导致漏掉某个因数;而整数除法i/j是纯整数运算,结果更准确。
对比你写的j < i,这个逻辑是正确的,但效率很低:比如i=97(质数),j < i要循环95次,而j <= i/j只需要循环到j=9(97/9≈10.7,j到9就停),循环7次就能完成判断。
2. 为什么j <= i时程序输出为空?
看你写的这段代码:
for(i=2; i < 100; i++) { isprime = true; for (j=2; j <= i; j++) if((i%j) == 0) isprime = false; if (isprime) System.out.println(i +" - is a prime number."); }
问题出在当j=i时,i%j的结果一定是0,不管i是不是质数。比如:
- 当
i=2(质数),j循环到2时,2%2=0,isprime被设为false; - 当
i=3(质数),j循环到3时,3%3=0,isprime也被设为false;
也就是说,所有数都会因为被自己整除,导致isprime最终是false,自然没有任何输出。
而质数的判断逻辑里,我们需要排除“被自身整除”的情况——因为质数允许被1和自身整除,所以判断时只需要检查2到i-1(也就是j < i),或者更优化的到√i,这样才不会误判质数。
内容的提问来源于stack exchange,提问作者Aleksei Surkov

