00:04
如果今天我们要算阶层。我们知道阶乘的定义是什么呢?任何一个数的阶乘就是从一乘二乘三一直乘到这个数为止。那个得出来的一个啊,相乘的结果叫做阶乘。比如说这里。这个三的阶层,那么答案就是六了,那么根据阶层的这个定义,我们怎么来算阶层呢?如果我们要写一个程序,让用户输入那个N。然后我们的程序能够输出N的阶层。我们怎么去想这个程序?我们反复在强调,我们学编程最主要的是什么?就是从问题到程序,这中间你是怎么过来的?我们现在要做这么一个事情了。我们说想程序的时候想两件事情,第一件事情是什么?就是我有什么样的数据要表达。我要让用户输入一个N,然后我去算这个N的阶层,那么显然这个N是我要表达的。
01:06
然后呢?我在做这个计算的时候会有个结果,那么当然这个阶层的结果肯定是我在计算当中要记录,最后要输出的,这肯定也是一个要表达的数据,那么计算的方法呢,当然这是一个非常简单的计算,它的计算呢直接做就可以了,另外呢,在这个计算的过程当中。我们显然需要有一个数,你看它一开始是一,然后是二,然后是三。不断的递增,最后呢,这个数要达到M为止,所以我们还需要有这样一个做计算时候的一个中间变量,我们来看看这个程序我们可以怎么写,首先我们需要有个变量N,它呢是从用户那里读进来的。然后呢,我们需要有一个变量呢,能够从一走到N,对不对啊,我们不妨呢把它叫做I,它呢一开始等于一。我们还需要有个变量,用来记录这个算出来的那个阶层的结果,我们就可以直接用阶层的英文单词。
02:07
这时候有一个问题,我们需要初始化这个变量,我们把它初始化为多少是合适零行不行?如果是零的话,我们知道我们后来要发生的事情一定是说这个factor要在某个地方呢,等于已经算好的factor再去乘以那个变化了的I。所以如果在这种情况下,你把这个factor初始化为零的话。那么以后所有的成都是都是零了,因此这种时候我们需要把它初始化为一。然后。我们需要有他要反复做嘛,所以肯定要有一个循环结构,我们按照之前的逻辑,我们知道说,诶我们我们先这么做,我们先把循环里面要做什么给他写出来,循环里面要做的事情是factor,要去乘那个I,然后呢I呢要等于I加一。那这些事情是放在一个循环结构里面的,这个时候用什么循环合适呢?While其实也挺合适的,对吧?如果I小于等于N的时候,我就要反复的做这个事情啊,一直到I大于N为止,我才不做这件事情,一旦做完了,那我们就可以输出我们的这个。
03:14
Factor的结果啊,那么这个factor的结果呢,就是那个。Factor变量,我们来试一下这个程序,我们看三的阶乘是六,这是对的。我们看六的阶乘720,我们想想,呃,三的阶层后面还要乘四乘五乘六,所以七百二应该是对的,我们可以再试一下十的阶层。已经是个蛮大的数字了,这是20的阶层。二线的阶层为什么会是负的?20的阶层是负的,说明我们的程序肯定有地方不对,什么地方不对呢?为什么它不能算很大的阶层?我们知道从数学上来说。自然数是没有边界的,我们有一个中间的点零,然后往正的方向,它会到无穷大,正的往负的方向,它当然也会到负的无穷大,它是没有边界的,这是123,你一直可以数下去。
04:15
这是在数学里头,可是就算在数学当中,我们知道说,如果给你一张白纸,让你写下一个你想得到的最大的数。或者说你你就啥也不管,就在这张白纸上把数字。从左上角开始,一点一点的写,写到右下角,你知道对于一张白纸来说,一张纸它也是有边界的,你从这儿开始写写写写写写写,总有一个写到右下角写不下去的时候。在这张白纸上,你能够表达的数其实还是有限的。你能够实际写出来的数是有限的,在计算机的内部,我们是用计算机的内存去表达我们的数据的,准确的说,对于我们这样的int类型来说,在计算机内部它是四个字节。
05:04
四个字节意味着它能够表达的数最大。是二的三十三十一次方减一,而最小的数呢?是负的二的31次方。只有在这个范围内的数啊。但得倒过来啊,它才是有效的。也就是说我们的Java的整数呢,Int类型呢,只能表达到这么大,那20的阶层其实是非常大的了。啊,因为这个阶层它涨起来是涨得很快的,所以20的阶层呢,是远远超过这个数,也就是说无法用int来表达的这样的一个数,回过来说,我们的这个程序呢,我们可以。改一个形式。把这个while改成另外一种循环,叫做for。为了做对比呢,我们把。这一段代码呢,给他。
06:00
注释起来啊,然后呢,我们在下面再来一段,如果这个循环是个负循环的话,我们会怎么写呢?啊,这就形成了我们的一个新的循环,这叫做for循环,因为它用的关键字是for。这个for循环呢,看上去有点奇怪啊,因为在for循环后面那个大括号里面不是只有一个条件,它通过分号分成了三个区块,这三个区块呢,各有各的作用啊,第一个区块其实做的是初始化的事情,你看这个循环进去,第一次来到这个循环的时候,我们要让I等于一,但是这这一步呢,以后是不会再做的,循环的下以后的每一轮都不做的啊,这是条件,这就像Y的那个条件一样,如果I小于等于N,那我这个循环要继续,而这句话是什么?这句话I等于I加一,不就是我们之前放在循环那一轮结束的时候要做的那件事情嘛。所以这个第三个区块呢,第三个表达式呢,就是循环体,这是我们的循环体,每一轮做完以后要去做的那个动作,这就是一个for循环。
07:10
它的语言括号里面是三个表达式,每个表达式有自己的作用,所以某种程度上呢,负循环就像一个计数器。我们设定一个计数器,初始化它,然后呢,在计数器到达某个值之前,我们要重复的反复不断的去做那个循环体,而每做一轮循环,计数器的值要以一定的步径去变化,可能是增长,可能是减少啊,总之啊,每一轮会做一些动作,就像我们现在这个程序一样,对于I这个变量啊,我们让它从零开始,初始化为零,只要I小于五,我们就做system out line I的这件事情,而循环的每一轮呢,I要加一。这样的话呢,它就形成了一个啊技术循环。这个循环的这个for里头的第一部,第一部分是个初始化啊,那么第二部分呢,是循环维持的条件,这和for和Y循环是一样的,这个条件是先验的,也就是说我进入循环之前,首先要检验这个条件是不是满足,条件满足我才进循环,条件不满足我就不进这个否循环了啊。第三个部分呢,是单步动作,就是说循环的每一轮这个循环题做完之后啊,我们要去做的事情,通常呢,我们会在这个地方去做修改我们的这个循环变量的这么一个动作啊。
08:26
我们如果把for念成对于的话,那么这句话的意思就是对于一开始的那个count等于零啊,啊,当然对于这句话来说啊,那就是对于一开始的count等于十,当count大于零的时候,我们做循环体内的语句啊,我们做我们的循环体,循环的每一轮结束以后,我们要使得count递减,Count等于count减义,这是一个递减的动作,所以我们可以把for呢念成对于,就可以把这三个表达式啊连起来,把这个for循环语句给它念出来了。那么我们的这个循环控制变量I,它只是在循环里面用的,你看我们的程序啊,在我们的这个程序里头呢,这个I在for循环里面用到了,那我现在这个eclipse的功能啊,我现在把所有用到I的地方都给它列出来了,不同的颜色啊,那么当然这个呃,黄色呢表明I被腐蚀的时候,这个灰色呢,表明I被使用的时候,所以。
09:21
I的所有出现的地方,除了定义以外,就是在这个循环体内,除了这个循环体还不存在了,那在这种情况下,我们可以再做一个改进,说我们把这个int写到这里来,当然这句话得去掉,这样做完之后呢,我们就在这个for循环里面定义了一个变量,叫做I,这个变量I只存在于for循环内部,在for循环里面可以用,除了for循环那就没有了,不相信如果我们在这儿说,我们还想让那个I等于零。它就会出错,它的错误呢,是说这个I不存在啊,I不是一个变量,所以这样定义的循环变量就只在for循环内部,用这个很方便啊,因为很多时候我们呃写到一个for循环了,我们觉得需要有个变量了,那我们直接写上in特I,我们就把这个变量给做出来了啊,但这I你可以换成你自己的名字啊,那么我们对比一下,我们看到左边是我们的wow的版本啊,右边是我们for的版本,在wow的版本呢,我们的这个循环控制变量I,它的定义和初始化是放在while语句的前面的,For来说呢,是放在for的大括号里面的,但是我们知道说实际上呢,这个事情的发生是在进for循环之前做的啊,或者说第一次进for循环的时候,我们做了这个动作,然后呢,While呢?要判断一个条件I是否小于等于n for也要判断这个条件I是否小于等于N,并且跟while一样,是进循环体之前先判断的,接着做循环体,在while循环的循环体还要做一句I等于加。
10:50
而在for循环呢,我们把这句话呢,放到for循环的第三个表达式里头去了,所以呢,循环题本身看上去会简洁一些。
11:00
呃,这个for循环和while循环的,他们俩之间总是可以互相替换的,我们总是可以把一个for循环改写成while循环,很简单,我们只要把for循环的第一句第一个表达式拿到while前面去。第二个表达式就是玩偶的条件,第三个表达式呢,放到循环体的最后一句去,我们就把一个for循环改造成玩偶循环了。那么如果你要把娃二循环改造成负循环呢?那么可能啊,呃,有的时候,比如说我可能没有要做初始化的事情,我可能没有每一步要做的事情,那么可能这些三个表达式里面呢,会有表达式是。没有必要去放一些必须做的表达式的,那么在这种情况下呢,呃,我们也可以去写出这样的for循环来,因为for当中的每一个表达式啊,都是可以省略的,如果你把初始化,初始动作省掉,把每一轮的动作也省掉,那么这个负循环呢,得写成这个样子,所以这里面的这些分号是不能省的,因为如果省了这个分号。
12:02
编译器就不知道你写的那个表达式到底是第一个呢还是第二个,你有了第一个分号,你把第一个表达式什么?有了第一个分号,那编译器就知道说这是第二个表达式,你再留下第二个分号,编译器就知道说OK,第三个表达式没有了。所以如果你把for循环写成这个样子,第一个、第三个都没有,那么它和while循环是完全等价的。啊,我们在讲if副语句的时候啊,曾经提到过,嗯,初学者在一副语句上面经常犯了一个小错误。就是在if的那个圆括号后面加了一个分号。那么对于循环语句来说也是一样的,如果你在在那个圆括号后面加了分号。那意思完全是另外一个意思。对于这个for循环来说,如果后面有分号,它的意思是什么呢?如果我们现在在这儿有一个分号。我们看到说。居然出了一个错误,说这个癌不存在。
13:01
我们明明在for里头定义了一个I了,对吧?这,这后面不是for的循环体吗?他说,哎,不存在。当然他肯定是对的是吧,那它问题在哪呢?因为这个分号的意思是这样。那就是说这个for循环什么都不做,这是一个空的for循环。空循环。然后这是for循环后面一个单独出现的那么一对大括号,当然这时候这个I就不存在了。啊,所以在这个for循环和while循环一样啊,和if语句一样,在那个圆括号后面不要去加分号,那当然我们的强烈建议就是只要是for语句,只要是while语句,就一定跟上一对大括号,Do你不会忘,通常不会忘,因为do while那个样子太古怪了,两个关键字你总会想到中间要有要有一对大括号,但是还是我们经常会看到很多,呃,写程序的时候,For循环只有一句话的时候,就把大括号给丢了啊,我们的建议啊,你还是要把大括号给加上去。
14:02
对于这样一个for循环,I从零开始到小于M,它的循环次数是多少?因为既然我们经常要用for循环来做计数的,那么要了解在这种负循环里面,它的循环次数,它的最后一个循环变量是多少,离开了这个循环以后,它的变量的值数多少就很有意义了,对不对?这事情其实我们在滑绕循环和多二循环的时候我们做过,那对于负循环来说,我们很很喜欢去把它写成从零开始到小于N这种局面,因为在这个时候呢,它的循环次数刚好就是N。但这里面有很多可以变化的,如果我不是从零开始,我是从一开始,然后结束的条件是小于等于N,那么它还是N,但是呢,在循环体内,这个I这个变量的。变化范围就不是从零到N减一,而是从一到M了,所以这里面有很多细节是需要去琢磨的,我们看到这是我们的三种循环,你可以分辨一下从左到右依次哪一种是哪个循环。
15:04
那面对这三种循环,我们的建议是说,如果你的循环你能够知道一个明确的次数的,那么我们就用for循环。比如说题目一开始告诉你说你。先读入一个数。N表示要做多少次,然后你怎么怎么怎么,那么很明白,这个时候用for循环是很合适的。如果。这个循环是必须要做一次的。那么这个时候用赌玩偶循环是最合适的,在其他情况下,那么我们可以考虑用玩偶循环。
我来说两句