循环结构的概念
先来看看生活中的一些场景:
(1)食堂阿姨打菜:接过顾客的餐盘→询问菜品→打菜→递回餐盘,重复以上过程,直到所有顾客的菜都打完了。
(2)快递员送快递:查看送件地址→赶往目的地→电话告知收件人→收件人签收→交快递件,重复以上过程,直到所有需要送的快递都处理完了。
(3)公交司机……
(4)作业流程……
以上场景都有一个共同的特点:有条件地重复地做一件事,每一次做的事情不同但类似。
程序是为了解决实际问题的,实际问题中存在着重复动作,那么程序中也应该有相应的描述,这就是循环。
案例:计算1+2+3+……+10
1 /*方案一*/ 2 var sum1 = 1+2+3+4+5+6+7+8+9+10; 3 /*方案二*/ 4 var sum2 = 0; 5 sum2 += 1; 6 sum2 += 2; 7 sum2 += 3; 8 sum2 += 4; 9 sum2 += 5; 10 sum2 += 6; 11 sum2 += 7; 12 sum2 += 8; 13 sum2 += 9; 14 sum2 += 10;
但是这两种方案的描述方式都不太理想,如果是要加到10000呢?
注意观察方案二,它重复地做一件事(将一个数加到sum2中),每一次做的不同但类似。
我们希望能找到一种更好的描述方法
1 *方案三:改造方案二*/ 2 var sum3 = 0; 3 var n = 1; 4 while(n <= 10){ 5 sum3 += n; 6 n++; 7 }
方案三表达的含义和方案二一样,但是表达方式要好得多,比如加到10000,只需要把条件n<=10改为n<=10000
while循环
while是表示“当……则……”,也就是当某个条件成立时,则一直重复做。
(调试工具查看程序运行轨迹以及变量的变化情况)
案例:输出所有水仙花数
1 <script> 2 var num = 100; 3 while (num <= 999) { 4 var num100 = Math.floor((num % 1000) / 100); 5 var num10 = Math.floor((num % 100) / 10); 6 var num1 = Math.floor((num % 10)); 7 var sum = Math.pow(num100, 3) + Math.pow(num10, 3) + Math.pow(num1, 3); 8 if(sum == num){ 9 alert(num+"是水仙花数"); 10 } 11 num++; 12 } 13 </script>
案例:GDP预测:
1 <script> 2 var year = 2009; 3 var gdp_usa = 142562.75; 4 var gdp_chn = 49089.82; 5 while(gdp_usa>gdp_chn){ 6 gdp_usa *= (1+0.02); 7 gdp_chn *= (1+0.08); 8 year++; 9 } 10 alert(year+"年,中国("+gdp_chn+")将超过美国("+gdp_usa+")"); 11 </script>
总结一下循环的套路
(1)初始状态
(2)循环条件
(3)循环体(要重复做的事情)
(4)为下次循环作准备()
那如何去写循环的程序呢?
拿到问题,不要胡思乱想,就回答四个问题:
(1)初始状态是怎样的?
(2)重复做的条件是什么
(3)重复做什么
(4)怎么过渡到下一次循环
案例:计算圆周率, π =(1 - 1/3 + 1/5 - 1/7 + ……)*4,计算到最后一项的绝对值小于10-6
分析:将公式稍微变化一下
1 - 1/3 + 1/5 - 1/7 +
变化为(+1/1)+(-1/3)+(+1/5)+(-1/7)
那么它和我们之前解决的1+2+3+……+10问题就非常类似了,即都是求累加和的问题,只不过每次加的内容不同而已。
我们可以将每一项拆分为三部分:
t = 符号*1/分母
(1)初始状态是怎样的?
sum = 0;
t = 1;
sign = 1;
deno = 1;
(2)重复做的条件是什么
|t|>=10-6
(3)重复做什么
sum += t;
(4)怎么过渡到下一次循环
sign = -sign;
deno += 2;
t = sign*1/deno;
for循环
1 <script> 2 /* 3 * 1.定义等腰三角形的行数 4 * 2. 5 * 3,*/ 6 var num=10; 7 //每一行的空格数为总行数减去当前是第几行 8 //每一行的星星个数为当前*2-1 9 //循环条件数小于等于10 10 for(var i=1;i<=num;i++){ 11 for(var j=num-i;j>0;j--){ 12 document.write("-"); 13 14 } 15 for(var k=1;k<=i*2-1;k++){ 16 document.write("%"); 17 } 18 document.write("</br>") 19 } 20 </script>
循环辅助语句
break:跳出所在的switch或者循环结构
案例:素数判断
1 var n = Number(prompt("请输入一个自然数")); 2 var m = Math.ceil(Math.sqrt(n));//根据相关数学定理,查找范围可缩小至[2,sqrt(n)] 3 var found = false;//找到因子的标记 4 for(var i=2; i<=m; i++){ 5 if(n%i == 0){ 6 found = true; 7 break;//找到则提前结束 8 } 9 } 10 alert(found?"不是素数":"是素数"); 11 continue:结束本次循环,开启下一次循环。
案例:对100以内既不是3的倍数也不是5的倍数的数求和
常规思路:对满足条件的数累加
1 var sum = 0; 2 for(var n=1; n<=100; n++){ 3 if(n%3!=0 && n%5!=0){ 4 sum += n; 5 } 6 } 7 alert(sum); 8 另一种思路:不满足条件的就放过 9 var sum = 0; 10 for(var n=1; n<=100; n++){ 11 if(n%3==0 || n%5==0){ 12 continue;//结束本次循环 13 } 14 sum += n; 15 } 16 alert(sum);
第二种思路的好处是:结构清晰
也就是我们在进行数据处理之前,先把各种不符合条件的情况先排除,然后在处理符合条件的情况(这个一般是程序的主体)
如果循环体的主体代码的执行有两个前提条件,常规思路是这么写的,如果循环体主体代码较多,该程序的可读性较差。
1 for(……){ 2 if(条件1){ 3 if(条件2){ 4 循环体主体代码(可能代码较多) 5 }else{ 6 alert("错误提示2") 7 } 8 }else{ 9 alert("错误提示1"); 10 } 11 }
换另外一个思路来描述,是这样的
1 for(……){ 2 if(!条件1){ 3 alert("错误提示1"); 4 continue; 5 } 6 if(!条件2){ 7 alert("错误提示2"); 8 continue; 9 } 10 循环体主体代码 11 }
break和continue的联系和区别
循环嵌套
for循环嵌套特点:
外层循环转一次,内层循环转一圈
外层循环控制行数,内层循环控制每行元素个数
案例1:找素数
1 <script> 2 /* 3 * 思路 4 * 素数:对于自然数,如果他只有1和他的本身之外再没有其他因子 5 * 解决思路: 6 * 1.提示并接收待判断的数n输入 7 * 2.在【2,n-1】之间去寻找因子, 8 * 3.如果找到则设置找到标志,并提前结束 9 * 4.根据标志输出相应结果*/ 10 var n =Number(prompt("请输入一个自然数")); 11 var found = false;//找到因子的标记 12 var m=Math.ceil(Math.sqrt(n));//根据数学的相关定理,判断范围可进一步缩小至{2,sqrt(n) 13 // for(var i=2; i<n-1; i++){ 14 for(var i=2; i<=m; i++){ 15 if(n%i == 0){ 16 found = true; 17 break;//找到则提前结束 18 } 19 } 20 alert(found?"不是素数":"是素数") 21 /* 22 * 三个关键 23 * 1.break;提前结束 24 * 2.标志位 25 * 3优化:根据定义,找因子的范围定义为{2,}n-1 26 * 肖为分析下,最大的因子不会超过n/2 27 * 即找到范围可缩小至{2,n/2} 28 * 根据数学的相关定理,判断范围可进一步缩小至{2,sqrt(n)}*/ 29 </script>
案例2:
做图形思路:
1确定图形一共几行 极为外层的循环的次数
2确定每行有几种元素,代表有几个内层循环。
3 确定每种元素的个数,即为每个内层循环的次数
tips:通常:找出每种元素个数,与行号的关系式,极为当前循环的最大值(从1开始循环)
[长方形]
*****
*****
*****
*****
for(var a=1;a<=5;a++){
for(var b=1;b<=5;b++){
document.write(b)
}
document.write("<br />");
}
[直角三角形]
*
**
***
****
*****
for(var a=1;a<=5;a++){
for(var b=1;b<=a;b++){
document.write(b)
}
document.write("<br />");
}
[平行四边形]
*****
*****
*****
*****
*****
for(var a=1;a<=5;a++){
for(var c=1;c<=a-1;c++){
document.write(" ")
}
for(var b=1;b<=5;b++){
document.write(b);
}
document.write("<br />")
}
[菱形]
* 1 3
*** 2 2
***** 3 1
******* 4 0
***** 1 5
*** 2 3
* 3 1
for(var a=1;a<=4; a++){
for(var c=1;c<=4-a;c++){
document.write("<span style='display: inline-block;width: 7px;'></span>")
}
for(var b=1;b<=2*a-1;b++){
document.write("*")
}
document.write("<br />")
}
for(var d=1;d<=3;d++ ){
for(var f=1;f<=d;f++){
document.write("<span style='display: inline-block;width: 7px;'></span>");
}
for(var e=1;e<=7-2*d;e++){
document.write("*")
}
document.write("<br />")
}