【Java编程】程序结构--循环2 (for)
目录
for循环语法结构
问题1:阶乘
关于 for 循环有以下几点说明:
问题2:判断 n 是否为素数(质数)
break 与 continue(只能对它所在那层循环做)
问题3:输出100以内的素数(包括100)
多重循环
问题4:前50个素数
问题5:九九乘法表
问题6:凑硬币
问题7:求和
问题8:最大公约数
辗转相除法(欧几里德法)
虽然所有循环结构都可以用 while 或者 do...while表示,但Java也提供了另一种语句 — for 循环,使一些循环结
构变得简单。for循环常用于遍历数组、列表,执行固定次数的操作等。在使用循环时,注意不要出现死循环。
Tips for loops:
有固定次数:for
必须执行一次,用do...while...
其他情况用while
史博:【Java编程】程序结构--循环1(while...和do...while)
for循环语法结构
for(循环变量初始化 ;循环条件;循环变量更新规则)
{
循环体程序
}
- 循环变量初始化:对应while是放在循环体外;
- 循环条件:对应while是放在while语句()内 ;
- 循环变量更新规则:对应while是放在while循环体内{} ;
问题1:阶乘
用户输入一个数n,然后程序计算输出n! (阶乘 n!=1*2*3*4...*n)
用do...while表达如下(思考步骤省略:变量-算法-流程图-程序)
Scanner in = new Scanner(System.in);int n = in.nextInt();int factor=1;while(n !=0){factor = factor * n;n --;}System.out.println(factor);
关于factor的初始化是1,不能写0。因为如果是0,那么乘啥结果都是0了(与累加区分)。将while改写为for:
Scanner in = new Scanner(System.in);int n = in.nextInt();int factor;for (factor = 1; n != 0; n--) { factor = factor * n;}System.out.println(factor);
另外还可以再定义一个变量 i 让他不断从1递增到n。那么代码如下:
int n = in.nextInt();
int factor = 1;
int i =1;for ( i =1; i<=n; i=i+1)
{factor = factor * i
}
System.out.println(factor);
for循环就像一个计数循环,设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执
行一轮循环,计数器值以一定步进进行调整,比如加1或者减1。
n 不能写很大的数,因为有内存空间限制。对于int类型来说,最大能写2^31-1。
for = “对于”
for (int i=1; i <=n; i=i+1)
读成:对于一开始的int i=1,当i <=n时,重复做循环体,每一轮循环在做完循环体语句后,使 i 递增。
关于 for 循环有以下几点说明:
- 最先,执行初始化步骤。可以声明一种类型,可初始化一个或多个循环控制变量,也可以是空语句。for(;条件;)==while(条件)。另外,用int n = 1或者n = 1都可。需要注意的是,变量 n 只在循环里被使用,在循环外没有任何用处,所以其他地方也需要用时,就须在循环体外定义。
- 然后,检测循环条件(布尔表达式的值)。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
- 执行一次循环后,更新循环控制变量。
- 最后,再次检测循环条件。循环上面的过程。
问题2:判断 n 是否为素数(质数)
思路
素数不能被除1和它自身以外的数整除。
可用从2开始的递增自然数一个一个去试。当余数为0时,说明遇到了可以整除的情况,则输入的 n 不是素数。
另外,只要 n 已经试到不是素数的情况,就要避免程序把所有的除数都给列举出来,用break,跳出循环。
Scanner in = new Scanner(System.in);int n = in.nextInt();for (int i = 2; i <= n - 1; i++){if (n % i == 0){System.out.println(n + "不是素数,能被" + i + "整除");break;}
但是,如何将是素数的 n 都记录下来?
这里需要增加一个状态变量 isPrime,初始值 isPrime = 1。当程序试出 n 不是素数时,就记录这个状态是 isPrime = 0。这样若一个数是素数,它不会进判断其不是素数的 if 循环,isPrime的值就不会变成0。之后再利用一个if...else...调用这个状态变量进行判断即可。
Scanner in = new Scanner(System.in);int n = in.nextInt();int isPrime = 1;for (int i = 2; i <= n - 1; i++){if (n % i == 0){isPrime = 0; //n 不是素数时,状态变为isPrime=0System.out.println(n + "不是素数,能被" + i + "整除");break;}}if(isPrime == 1) // 用== 关系运算符,检查两个操作数的值是否相等,如果想等为true {System.out.println(n +"是素数");}
注意:用” == “是关系运算符,检查isPrime当下被赋的值是不是和 1 相等,如果是为true,这是一个关系判断。用"="(赋值)报错。
break 与 continue(只能对它所在那层循环做)
break:跳出循环
continue:跳过循环这轮,剩下的语句进入下一轮

break与continue
问题3:输出100以内的素数(包括100)
多重循环
这次的 n 不是某个固定值了,而是 n 会从2开始循环到100里面的每个数,所以再嵌套一层循环。
同时,把 int n = in.nextInt()注释掉。这里要注意 isPrime=1的位置,需要放在for(n的循环)里面,不然当isPrime
的状态变成0后,就不会重置为1,后续所有素数都不会显示。
// Scanner in = new Scanner(System.in);
// int n = in.nextInt();int n =2;for (n = 2; n <= 100; n++){int isPrime = 1;for (int i = 2; i <= n - 1; i++) {if (n % i == 0) {isPrime = 0;// System.out.println(n + "不是素数,能被" + i + "整除");break;}}if (isPrime == 1){System.out.print(n + " ");}}
问题4:前50个素数
思路
区别上一题之处在于,“前50个”我们并不知道n的for循环的边界在哪里,可能是n<=100、 n<200 或 n<220。这
个边界是不确定的,所以得for...和while...格式转换的规则,换while循环。再增加对素数计数的变量count。count
从0开始,需要50个数,循环条件用 &&(与) count <50。
int n =2;int count=0;do{int isPrime = 1;for (int i = 2; i <= n - 1; i++) {if (n % i == 0) {isPrime = 0;// System.out.println(n + "不是素数,能被" + i + "整除");break;}}if (isPrime == 1){System.out.print(n + " ");count ++;}n++;}while (n >=2 && count < 50 );
问题5:九九乘法表
int i;int j;int result=1;for( i=1;i<=9;i++ ){for( j =1; j<=9; j++) {result = i * j;System.out.println(result);}}
注意 “\t” 的用法,这样可以让乘法表9个9个输出。
for( int i=1; i<=9; i++ ){for( int j =1; j<=i; j++) { //j<=9 与j<=i的区别System.out.printf("%d*%d=%d\t",i,j,i*j);}System.out.println();}

问题6:凑硬币
如何用1角、2角和5角硬币凑出10元以下的金额?(不包括10元)
思路
为了方便,将10元换成100角,这样就类似前面的凑100以内数的题。
1. 输入:10元以下的金额用 amount 接收,
1角张数 one,2角张数 two,5角张数 five。
2. 算法:先假设给定1个固定 amout 值。用枚举法先大额递增循环(5角),再套(2角)的递增循环,最后里面
是(1角)的递增循环。然后,用 if 函数,判断 "one + 2* two + 5*five"的值,是否等价于"==" amount 的值。最
后,将单一 amount 值套上循环,把所有可能情况列出。
3. 输出:所有10元以下的金额的凑数方案。
double amount =10;int one =0;int two =0;int five =0;for(amount =1; amount <100; amount++){ OUT:for (five = 0; 5 * five <= amount; five++){for (two = 0; 2 * two <= amount; two++){for (one = 0; one <= amount; one++){if (one + 2 * two + 5 * five == amount){System.out.println((double) amount / 10 + "元 : " + five + "张5角 / " + two + "张2角 / " + one + "张1角 组成");break OUT;}}}}}
截出1.0元的凑数结果如下(5角的循环在3层里面的最外层)
1.0元 : 0张5角 / 0张2角 / 10张1角 组成
1.0元 : 0张5角 / 1张2角 / 8张1角 组成
1.0元 : 0张5角 / 2张2角 / 6张1角 组成
1.0元 : 0张5角 / 3张2角 / 4张1角 组成
1.0元 : 0张5角 / 4张2角 / 2张1角 组成
1.0元 : 0张5角 / 5张2角 / 0张1角 组成
1.0元 : 1张5角 / 0张2角 / 5张1角 组成
1.0元 : 1张5角 / 1张2角 / 3张1角 组成
1.0元 : 1张5角 / 2张2角 / 1张1角 组成
1.0元 : 2张5角 / 0张2角 / 0张1角 组成
扩展
如果需要每个 amount 值找到一个方案,就不需要再找凑数方案,继续找下一个 amount 值。需要怎么处理?
可以用之前标记状态的方法 isExit = 1,然后一层一层退出 isExit =1 break(break和continue只能跳出自己所在的
循环)。也可以在想跳出的那层循环上增加一个标号"OUT:"。这样OUT下面的那层循环可跳出。
如果先用大面额的5角凑,再用2角凑,这样需要的纸币较少,1角也不用写循环。
只是要注意5角和2角的循环起始的数,以及更新规则。

凑数字“11”的结果
Scanner in = new Scanner(System.in);int amount = in.nextInt(); //系统输入一个数int one;int two;int five;for (five = amount/5; five >=0; five--) // 5角的起始数= amount / 5 的商 {for (two = (amount-5*five) / 2; two >=0; two--) // 2角的起始数= (amount-5*five) / 2{one = amount-5*five-2*two; // 1角直接公式输出System.out.println((double) amount / 10 + "元 : " + five + "张5角 / " + two + "张2角 / " + one + "张1角 组成");}}
问题7:求和

Scanner in = new Scanner(System.in);
int n =in.nextInt();
double sum=0.0;for (int i=1; i<=n; i++)
{sum = sum + (double)1/i ;
}System.out.printf("%.2f",sum); // 做四舍五入 .printf("%.2f",sum)

变型
Scanner in = new Scanner(System.in);int n =in.nextInt();double sum1=0.0;double sum2=0.0;double result=0;for (int i=1; i<=n; i++){if( i %2 ==0 ){sum1 = sum1 - (1.0/i);}else{sum2 = sum2 + (1.0/i);}result = sum1 +sum2;}System.out.printf("%.2f",result); //"%.2f", 做四舍五入
上面所有分母是偶数的情况下,分数前面都是负号,合在一起求sum1,分母是奇数的情况求sum2,最后的result
是两部分合并的结果。另外,一种思路是利用 -1 和 1 来标记符号变化。
Scanner in = new Scanner(System.in);int n =in.nextInt();double sum=0.0;int sign =1;for (int i=1; i<=n; i++, sign = -sign) // 有多个更新规则的话,可以用逗号隔开{sum = sum + 1.0/i;}System.out.printf("%.2f",sum);
问题8:最大公约数
输入两个正数a和b,输出它们的最大公约数(输入:12、18 输出:6)
思路(枚举法)
用数字2、3、4... i 去一一试,看 a 能否被 i 整除,同时b也能被 i 整除(a % i ==0&& b % i ==0)。
之后,用变量gcd(公约数)记录,gcd 会不断被递增更新。最后,打印最末一次的 gcd 就是它们的最大公约数。
Scanner in = new Scanner(System.in);int a = in.nextInt();int b = in.nextInt();int i;int gcd = 1; //gcd最大公约数for (i = 1; i <= Math.min(a,b); i++) {if (a % i == 0 && b % i == 0) {gcd = i;}}System.out.print("最大公约数:" + gcd);
循环继续下去的条件用最大公约数的定义。如果写 i <=100,也不会影响循环打印出来的结果。因为能做if里面“
% ==0 和 && “的计算,就说明 i 已经满足了"i<=a && <=b"(即i <=Math.min(a,b))的条件,只是会多一些
没意义的循环过程。
枚举法的思路,我尝试写出来后,可能不太一目了然。不过不知道是不是会少些计算?
Scanner in = new Scanner(System.in);int a = in.nextInt();int b = in.nextInt();int c =1;int i;int ret = 1; //最大公约数for (i = 1; i <= a && i <= b ; i++){if (a % i == 0){c = i; //c是a的约数,用c去除b,如果整除,那么ret就等于c,打印if (b % c ==0)ret = c;}}System.out.print("最大公约数:"+ ret);
用第一个if,得到 a 的约数,用变量 c 记录。既然是公约数,那么拿着这个 a 的约数 c ,再去除 b,也会在 c 的基
础上把是 b 的约数挑出来。这步感觉比“同时拿一个数去试一次 a,再试一次b ,最后判断是否是&&的关系”要少
了一些计算。因为 c 里面的数少了,需要跟b试的计算也少了。
辗转相除法(欧几里德法)
1. 如果b等于0,计算结束,a就是最大公约数;
2. 否则,计算 a 除以 b 的余数,让 a 等于 b,而 b 等于那个余数;
3. 回到第一步。
Scanner in = new Scanner(System.in);int a = in.nextInt();int b = in.nextInt();int r;int oa =a; //为了下面写结论方便看originalint ob =b;while(b != 0){r = a%b ;a = b;b = r;}System.out.println(oa+"和"+ob+"的最大公约数:"+a);
希望通过上面的例子,可以帮助大家更好的理解for()循环,下一篇将是关于数组的基础内容。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
