复写了三段代码,有一些感悟,索性记录下来..
2.6 判断水仙花数
首先明白什么叫水仙花数:指一个三位数,各位数字的立方和等于该数的本身。举例:152是一个水仙花数,因为
题设要求打印出所有的水仙花数,那么不废话直接上代码:
public class Demo0206_DaffodilNum{
public static void main(String args[]){
int gw,sw,bw;
for(int n = 101;n<1000;n++){
bw = n/100; //百位
sw = n%100/10; //十位
gw = n%10; //个位
if(bw*bw*bw + Math.pow(gw, 3) + Math.pow(sw, 3) == n){
System.out.println(n+"是一个水仙花数");
}
}
}
}
一段非常简单的代码,用C语言或者C++大家应该都知道,对于Java也大差不差,唯一需要注意的一点就是调用 pow() 函数时与C语言C++不同,C语言C++中是通过头文件 math.h 或 cmath.h 调用
而在Java中是通过 Math 类来完成一些数学中的操作的 。
Math 类位于 java.lang 包,它的构造方法是 private 的,因此无法直接创建 Math 类的对象,并且 Math 类中的所有方法都是类方法,所以我们可以直接通过类名来调用它们,不需要导入包之类的操作。
如此例中的 Math.pow() 就是通过 Math 类调用 pow() 函数。pow()函数的作用是达到a的b次方的效果,a是先传入的值,b是后传入的值。如 pow(a, b) ,表示的就是a的b次方。此例中的 Math.pow(gw, 3) 表示的就是 gw 的三次方。注意Math的首字母需要大写!
2.7 判断101-200间有多少素数,并且打印出来
素数大家都知道,就是除了1和它本身没有其他自然数整除的数。要求素数很简单,只需要将原数与2到它本身前一个数间所有的数做取模运算就行,若是取模都不为0,那么该数就是素数。
但是这种方法需要遍历的数太多了,100、1000还好,如果是一千万、一亿等等更大的数,那么让计算机从头遍历这么多数是十分消耗内存的,所需要的时间也是巨大的。因此我们采用更加省时省空间的方法
public class Demo0207_primeNum{
public static void main(String[] args){
int count = 0;
for(int i = 101;i<200;i+=2){
//设置一个状态布尔变量,用于表示该数是否为素数
boolean isPrime = false;
for(int j = 2;j<=Math.sqrt(i);j++)
{
if(i%j==0){
isPrime = false;
break;}
else{
isPrime = true;}
}
if(isPrime==true)
{
//此段代码是用于输出素数并且达到换行的操作
count++;
System.out.print(i+" ");
if(count%5==0)
System.out.println();
}
}
System.out.println();
System.out.println("素数的个数是:"+count);
}
}
代码有点长,但是一些需要注意点做出了一些基础的解释,其中最重要的一段就是 Math.sqrt(i) 。
在C语言C++中我们也学习过,sqrt就是对括号内的数进行开平方运算,那么为什么要进行开平方运算呢?举个例子:100,开平方为10。我们来列出他的因子:2、4、5、10、20、25、50。可以清晰地看出,其中每一个小于开平方数的因子,始终有一个大于开平方数的数与之对应。这就是为什么要使用函数 sqrt() 了。
(除以二也可以节省空间,在某些时候也很好用,但在本例中,开平方节省的时间和空间多得多,因此我们使用更加高效的开平方运算)
2.8 正整数分解成素因数
我并不知道素因数的概念,但是题设给出了一个例子: 90 = 2*3*3*5。大概也了解了题目要我们求的东西是什么,首先上代码
import java.util.Scanner;
public class Demo0208_DecPrimeFactor{
public static void main(String args[]){
Scanner s = new Scanner(System.in);
System.out.print("请输入一个正整数:");
int n = s.nextInt();
int k = 2;
System.out.print(n+" = ");
while(k<=n){
//从2开始遍历循环,到本身的时候结束
if(k==n){
//若是遍历到的数与输入值相等,那么直接输出输入值,循环结束
System.out.println(n);break;
}
else if( n%k == 0 ){
//如果遍历到的数与输入值不相等,且n对k取模为零,那么表示k为n的一个因子
//输出k的值加上一个符号*
System.out.print(k+"*");
//将n除以因子k,得到的数继续参与循环
n = n/k;
}
//若以上两个条件都不成立!k再自增,参与循环
//(注:一定得是上述循环不成立才进行该语句!)
else k++;
}
}
}
代码中有一些新的东西,我们一一来看
(1) 输入操作:
在Java中进行信息的输入有些麻烦。首先输入信息并不像C语言C++那样scanf或者cin。之前提到过Java里面都是类,输入操作也不例外,但是进行信息输入的类与 Math 类不一样,我们无法直接调用它,首先得导入这个类,我们通过 import java.util.Scanner; 便可以将 Scanner 类导入(若是导入其他的类或者包也是通过 import + 包名/类名 完成,一般来说通过 包.类 的操作较多)。
导入了类之后,我们需要将这个类进行实例化:
Scanner s = new Scanner(System.in);
与C语言C++的实例化有相似之处, Scanner 是类名,s是实例化的对象名称,通过关键字 new 为实例化的对象申请一片空间,括号内传入的是我们要输入的信息(System也是一个类,输入输出都得靠它,out是输出,in是输入),之后每一次的输入都需要通过对象调用类内的函数才行。
int n = s.nextInt();
nextInt()表示的就是读取下一个整型(将你输入的整型数赋值给n)
一些常用的Scanner方法
方法 | 功能 |
---|---|
next() | 读取下一个字符串,以空格为分隔符 |
nextLine() | 读取下一行字符串,以回车符为分隔符 |
nextInt() | 读取下一个整数 |
nextDouble() | 读取下一个双精度浮点数 |
hasNext() | 判断是否还有下一个输入项 |
hasNextLine() | 判断是否还有下一行输入项 |
useDelimiter() | 设置分隔符 |
close() | 关闭Scanner对象 |
如果觉得每次调用 Scanner 类有些麻烦的话(有时候一个程序要进行很多次输入),我们不妨定义一个类,并且定义一个函数,在其中写入 Scanner 类的实例化等操作,同时也写入 nextInt() 等输入值时需调用的函数,这样的话每次需要完成输入操作时,只需要进行类中函数的调用即可,在某些时候大大简化了输入操作,下面是写的类
class input{
public int input(){
int value = 0;
Scanner s = new Scanner(System.in);
value = s.nextInt();
return value;
}
}
在进行输入操作时只需要输入一下代码即可:
input fymd = new input(); //对input类实例化
x = fymd.input(); //直接调用输入函数
在多次进行输入的时候可以简化操作(具体可以看书上的 2.10 代码),需要注意的事该操作无法帮我们省去导入 Scanner 类的操作 ,每次程序的开头还是需要导入 Scanner 类(就一句话也用不着省吧)
(2)对于最后一段 else k++;
一定要注意是上面的两个if语句都不成立之后才能进入k的自增,这样做是为了防止输入的n值有两个相同的素因子(类似与 18 有两个相同的素因子 3 ,即:18 = 2*3*3,如果 k 没有经历上面两个循环就自增,那么会漏掉一个素因子 )
(3)分析各阶段各值
以传入的 90 为例,将 while() 循环的次数记为第几次循环,将 if 语句的段数记为第几段 if 语句,并且同时记录语句是否进入语句,产生的结果为什么,来分析一下各阶段各参数的值,辅助理解语句
第几次循环 | n | k | 第几段if语句 | 是否进入语句,产生结果为什么 |
---|---|---|---|---|
第一次循环 | 90 | 2 | 第一段 | n不等于k,不进入语句 |
第一次循环 | 90 | 2 | 第二段 | n对k取模为0,进入语句 结果为 n = n/k = 45 直接加入下一次循环 |
第二次循环 | 45 | 2 | 第一段 | n不等于k,不进入语句 |
第二次循环 | 45 | 2 | 第二段 | n无法对k取模,不进入语句 |
第二次循环 | 45 | 2 | 第三段 | 上两段语句无法进入,k++ |
第三次循环 | 45 | 3 | 第一段 | n不等于k,不进入语句 |
第三次循环 | 45 | 3 | 第二段 | n对k取模为0,进入语句 结果为 n = n/k = 15 直接加入下一次循环 |
第四次循环 | 15 | 3 | 第一段 | n不等于k,不进入语句 |
第四次循环 | 15 | 3 | 第二段 | n对k取模为0,进入语句 结果为 n = n/k = 5 直接加入下一次循环 |
第五次循环 | 5 | 3 | 第一段 | n不等于k,不进入语句 |
第五次循环 | 5 | 3 | 第二段 | n无法对k取模,不进入语句 |
第五次循环 | 5 | 3 | 第三段 | 上两段语句无法进入,k++ |
第六次循环 | 5 | 4 | …… | 三段语句与第五次循环一样,k++ |
第七次循环 | 5 | 5 | 第一段 | n = k,直接输出n,退出循环 |
最后得出的输出即为题设所要求的 素因数。
以上便是复写三段代码的一些感悟,人已疯 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊