双重循环嵌套执行原理(逆战班)
这里为了大家更容易理解,我选择利用for循环做一个质数之和的写法,配合浏览器断点功能进行解释。
<script>
/* 只能被1和它自身除尽的数称为质数 */
let sum = 0;
// 质数是一个大于1的自然数,所以定义的变量i=2,从2开始循环
// 并且这里只计算100以内的质数,所以循环到100的时候就跳出
for (let i = 2; i < 100; i++) {
// 定义一个变量s,当每次循环结果是质数或非质数,输出不同的s值
let s = 1;
// 定义一个变量j,并且j的值要一直小于i
for (let j = 2; j < i; j++) {
// 上面说的要j的值一直小于i.目的就是为了让i除以j来取余
if (i % j === 0) {
// 当i除以j取余为零,s输出结果就赋值为0.也就是除尽了,不是质数
s = 0;
// 跳出当前循环,会重新定义s=1.
break;
}
}
// 这里s===1也就意味着前面没除尽的数,没有对s进行改变,所以s为原来的初始状态.
// 也就是质数
if (s === 1) {
console.log(i + '这是质数');
// 将最先定义的一个为0的变量不断累加i的值,得到的就是质数的和。
sum += i;
}
if (s === 0) {
console.log(i + '这不是质数');
}
}
// 最后输出质数的总和。
console.log(sum);
</script>
在上述代码中,我们可以清楚了了解每行代码的作用和意义.下面我们来用浏览器的断点功能看看双重循环嵌套执行的原理是什么吧。
可以看到,初始状态下,i是没有赋值的。
当我们开始下一步,就给i赋值为2.接着就会判断i是否小于100.如果小于,就执行{}花括号内的语句块。
这里跳过了let s = 1的过程,直接看内层循环,当定义变量j并赋值为2的时候,判断j是否小于此时的i。我们知道,此时的i的值也为2.也就是说j等于i。就不执行此次循环,况且自然数只有除以1或者它本身能除尽,那它是质数,这个2可以直接判断为是质数。
这里就直接不执行内层循环,跳到了
if (s === 1) {
console.log(i + '这是质数');
// 将最先定义的一个为0的变量不断累加i的值,得到的就是质数的和。
sum += i;
}
并将i的值累加到sum上,此时sum就等于2了。
下一步执行了i++,让i加1之后,再次判断i是否小于100,满足条件,再次执行循环内的语句块。
中间简易部分跳过:
当执行循环内语句块时,又执行到了内层循环,重新定义j,赋值2,此时i已经经过了i++变成了3.这时j就满足小于i的条件,将执行内层循环内的语句块.
这里可以直接看出,如果i%j === 0 ,就给s赋值为0再跳出,但是此时的i%j不为零,所以不会执行if内的语句块,直接进行j++,再次判断j是否小于i。而经过了j++,j又等于3,i也一直是3,那么又将直接跳出,s的值依旧没有改变,所以3也是质数,并且累加到sum当中,然后再次i++,进行判断i是否小于100,而此时i就已经为4了。那么执行循环内的语句块时,内层循环:
for (let j = 2; j < i; j++)
就相当于是:
for (let j = 2; 2 < 4; j++)
执行内层循环的语句块, i%j === 0 ,是成立的,所以赋值s=0,并跳出内层循环,然后在控制台打印一个:4 这不是质数
然后再次执行外层循环最后的i++,开始判断5是不是质数,以此内推,会一直循环到i=100时,跳出所有循环。
再打印一个sum,也就是质数累加的结果。
这样我们就得到了一百以内,所有质数的总和为:1060.
注:这里定义sum变量时,一定不要讲它定义在循环内,不然每次循环都将重新定义sum的值为0.就得不到质数累加的结果。