Skip to content

Commit bc3a5e3

Browse files
committed
finish some examples
1 parent 82e3468 commit bc3a5e3

File tree

2 files changed

+204
-1
lines changed

2 files changed

+204
-1
lines changed

Lesson07/Lesson07.md

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,123 @@ B:“所以你才是猪”
2424

2525
### while
2626

27+
我们直接来看看怎么写**while循环**的代码:
28+
29+
```java
30+
while(condition) {
31+
statements;
32+
...
33+
}
34+
```
35+
36+
- `condition`:一个布尔值(可以理解为一个事件)。若为真,则继续循环;若为假,则跳出循环
37+
- `statements`:循环体,当condition成立时则会执行
38+
39+
具体的过程解释:当程序执行到`while`语句块时,会****判断`condition`是否为**true**。若为**true**,则执行一遍循环体;否则将继续执行while语句块之后的语句。
40+
41+
希望下面的流程图可以帮助大家具体化地熟悉整个流程:
42+
2743
![while](./while.png)
2844

45+
那么**循环的要素**是哪些呢:
46+
47+
1. 循环继续(跳出)的**条件**
48+
2. 循环体的**具体内容**,注意那些不变的逻辑
49+
3. 注意每次迭代**哪些变量需要变**
50+
51+
52+
53+
### Example
54+
55+
在继续看其他的循环结构之前,我们先来看一个简单的例子:
56+
57+
#### 输出所有三位数的水仙花数
58+
59+
水仙花数:个位数的立方+十位数的立方+百位数的立方=这个数本身
60+
61+
在这节课的开头的时候我就说过,注意计算机最适合做重复的工作。所以比起探索出水仙花数的构造规律,计算机最会干的反而是**枚举法**。每当需要尝试的数的集合是有限集时,都可以考虑使用枚举法!在这个题中,我们枚举所有的三位数,逐个判断其是否是一个水仙花数。
62+
63+
64+
65+
大家可以先自己尝试写出来,再看下面的解释以及标准程序哦!
66+
67+
68+
69+
首先我们设一个**变量i**,用于装要检查的那些数。初始我们将其设为100,从100开始逐个检查,因为100是第一个三位数。
70+
71+
注意刚刚说的循环的三要素:
72+
73+
- **继续条件**:或者这里就是说我们要枚举哪些数嘛,肯定是100~999之间的所有的三位数,由于初始i为100,而最终i为999,也就是说**i**满足`i <= 999`时,都要继续进行检查操作
74+
- **变的变量**:这里我们为了简单,我们就逐个逐个地来进行判断每次循环的最后,我们都执行`i++`,这样下次迭代就会检测下一个待测数
75+
- **循环体**:也就是不变的那一部分逻辑,这里自然就是检查**i是不是一个水仙花数**,判断大家已经在上节课学过,在这里我就不作赘述
76+
77+
接下来就是标准程序啦:
78+
79+
```java
80+
public class TestNarcissus {
81+
public static void main(String[] args) {
82+
83+
System.out.println("3-digit narcissus numbers: ")\
84+
85+
int i = 100; // starts from 100
86+
while(i <= 999) { // ends at 999
87+
88+
// get the number of each digit
89+
int bai = i / 100;
90+
int shi = i / 10 % 10;
91+
int ge = i % 10;
92+
93+
// judge if i is a narcissus number
94+
if (bai*bai*bai + shi*shi*shi + ge*ge*ge == i) {
95+
System.out.println(i);
96+
}
97+
98+
// remember to go to the next i
99+
i++;
100+
}
101+
}
102+
}
103+
```
104+
29105

30106

31107
### do-while
32108

109+
我们直接来看看怎么写**do-while循环**的代码:
110+
111+
```java
112+
do {
113+
statements;
114+
...
115+
} while(condition);
116+
```
117+
118+
- `condition`:一个布尔值(可以理解为一个事件)。若为真,则继续循环;若为假,则跳出循环
119+
- `statements`:循环体,当condition成立时则会执行
120+
121+
具体的过程解释:当程序执行到`do-while`语句块时,会****执行一遍循环体,再判断`condition`是否为**true**。若为**true**,则再次执行循环体;否则将继续执行do-while语句块之后的语句。
122+
123+
流程图如下:
124+
33125
![dowhile](./dowhile.png)
34126

35127

36128

37129
### for
38130

131+
132+
39133
![for](./for.png)
40134

41135

42136

43137
### 练习
44138

45-
输出前从2开始的前n个质数
139+
1. 猜数游戏
140+
141+
程序生成一个1~100以内的随机数(`(int)(Math.random() * 100 + 1)`),之后不断让用户输入自己猜的数字。若猜对了,打印恭喜的小短语,结束程序;若没猜对,告知用户目标数是比他刚才猜的数字大还是小。
142+
143+
2. 输出从2开始的前n个质数
46144

47145

48146

Lesson07/是玄学吗.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# 是玄学吗
2+
3+
## 题目在这里~
4+
5+
这个是计算机初学者可能不能理解的问题……
6+
7+
来看下面这段代码:
8+
9+
```java
10+
double t = 0.2;
11+
for(int i = 0; i < 50; i++) {
12+
System.out.println(t);
13+
t = 1 - 4 * t;
14+
}
15+
```
16+
17+
输出是什么?不知道的话请自己试试哦!(解释在下面!)
18+
19+
20+
21+
22+
23+
24+
25+
26+
27+
28+
29+
30+
31+
32+
33+
## 解释
34+
35+
稍微有点编程基础的人会说,这好像会打印出来50行,每行一个0.2?
36+
37+
38+
39+
按照这段程序的逻辑来说是的确这样的,但是实际的输出是这样的:
40+
41+
```
42+
0.2
43+
0.19999999999999996
44+
0.20000000000000018
45+
0.1999999999999993
46+
0.20000000000000284
47+
0.19999999999998863
48+
0.20000000000004547
49+
0.1999999999998181
50+
0.2000000000007276
51+
0.19999999999708962
52+
0.20000000001164153
53+
0.19999999995343387
54+
0.20000000018626451
55+
0.19999999925494194
56+
0.20000000298023224
57+
0.19999998807907104
58+
0.20000004768371582
59+
0.19999980926513672
60+
0.20000076293945312
61+
0.1999969482421875
62+
0.20001220703125
63+
0.199951171875
64+
0.2001953125
65+
0.19921875
66+
0.203125
67+
0.1875
68+
0.25
69+
0.0
70+
1.0
71+
-3.0
72+
13.0
73+
-51.0
74+
205.0
75+
-819.0
76+
3277.0
77+
-13107.0
78+
52429.0
79+
-209715.0
80+
838861.0
81+
-3355443.0
82+
1.3421773E7
83+
-5.3687091E7
84+
2.14748365E8
85+
-8.58993459E8
86+
3.435973837E9
87+
-1.3743895347E10
88+
5.4975581389E10
89+
-2.19902325555E11
90+
8.79609302221E11
91+
-3.518437208883E12
92+
```
93+
94+
不难发现,误差越来越大,越来越偏离原来的0.2
95+
96+
误差从何而来?我们知道计算机是用二进制来表示数的,那么0.2该如何表示?
97+
98+
$0.2_{(10)} = 0.0011001100110011..._{(2)}$
99+
100+
最后应当是0011**无限循环**下去的,也就是说0.2是不可能被**有限**位数的double数据类型精确表示的。
101+
102+
这就像是一种蝴蝶效应,原本double表示0.2的精度的微小误差被`*4`一次次放大,最后误差甚至都到达了$10^{11}$之多。
103+
104+
不过不用担心在日常的编程过程中会出现这样的问题,因为我们一般都会使用四舍五入(`System.out.printf("%.2f", t);`)浮点数运算的结果,而且在以$10^{-5}$为标准的精度下,做20次这样的乘法以及减法运算才出现了这样的误差,在日常的编程中,还是比较容易避免的。
105+

0 commit comments

Comments
 (0)