从欧几里得开始(二)
从欧几里得开始(二)
承接上文,找到判定一个自然数约数的算法流程图是以下这幅图,经过几次修改(图中带有颜色的部分都是修改的地方)

用java语言采用一一对应的原则,把这幅算法图翻译成了java代码,里面的注释是标志算法图中各个部分的对应。
public class factor {
public static void main(String[] argv)
{
int input_testnumber =2; // 被测试的数a 初值化
int input_naturalnubmer =28; //自然数N 初值化
Boolean result; // 测试结果, true 或者 false
int k = 1;
if( input_testnumber == input_naturalnubmer) result =true; // 第一个判定过程 a=N?
if(input_testnumber <= Math.floor(input_naturalnubmer/2)) { // 第二个判定过程 a<=[N/2]?符号限制原因用[]代替表示取整
for(;k<=Math.floor(input_naturalnubmer/input_testnumber);k++) // 迭代过程开始
{
if(input_naturalnubmer == k*input_testnumber) // 第三个判定过程 ak=N?
{
result = true; break; //迭代出口1,出口向外输出true
}
}
result = false; // 迭代出口2, 向外输出 false
}
else
result = false; //第二个判定过程的另外一个出口,false值
// 到此,算法图中所有的内容都完成了,现在展示一下结果。
//以下,这是展示结果用的
if(result == true)
System.out.println(input_testnumber +" 是 " + input_naturalnubmer + " 的约数 ");
else
System.out.println(input_testnumber + " 不是 " + input_naturalnubmer + "的约数");
}
}
上面是很原生态的翻译,你一眼看上去会发现,这些代码是陌生的,估计只有写这个的人,或者多看几遍的人,才能清楚这个在干什么。这是一件十分糟糕的事情,但是,一些命名和编程语言内在的抽象化功能,能够使这件糟糕的事情变成好一些。
我将整个判定过程合在一起,输入是两个整数,输出是一个Boolean值,这个合起来后的名称叫factorOf
这个过程完成的是这样一个转换:factorOf : (int,int) -> Boolean
public class factor {
public static void main(String[] argv)
{
int input_testnumber =2; // 被测试的数a 初值化
int input_naturalnubmer =28; //自然数N 初值化
Boolean result; // 测试结果, true 或者 false
result = factorOf(input_testnumber, input_naturalnubmer); // 整个判定逻辑用factorOf这个过程替代
// 到此,算法图中所有的内容都完成了,现在展示一下结果。
//以下,这是展示结果用的
if(result = true)
System.out.println(input_testnumber +" 是 " + input_naturalnubmer + " 的约数 ");
else
System.out.println(input_testnumber + " 不是 " + input_naturalnubmer + "的约数");
}
//这是factorOf的具体实现,其实就是将上面的代码原样写出来,把输入和输出修改成合适的变量和返回值
public static Boolean factorOf(int a, int N)
{
int k = 1;
if( a== N) return true; // 第一个判定过程 a=N?
if(a <= Math.floor(N/2)) { // 第二个判定过程 a<=[N/2]? 符号限制原因用[]代替表示取整
for(;k<=Math.floor(N/a);k++) // 迭代过程开始
{
if(N == k*a) // 第三个判定过程 ak=N?
{
return true; //迭代出口1,出口向外输出true
}
}
return false; // 迭代出口2, 向外输出 false
}
else
return false; //第二个判定过程的另外一个出口,false值
}
}
同样的思路,我们优化一下展示结果,把展示部分写成命名为show,
show:(Boolean, int,int) -> 对输出流产生影响(详细的说就是在console里面打字出来)
public class factor {
public static void main(String[] argv)
{
int input_testnumber =2; // 被测试的数a 初值化
int input_naturalnubmer =28; //自然数N 初值化
Boolean result; // 测试结果, true 或者 false
result = factorOf(input_testnumber, input_naturalnubmer); //
// 到此,算法图中所有的内容都完成了,现在展示一下结果。
//以下,这是展示结果用的
show(result,input_testnumber,input_naturalnubmer);
}
public static Boolean factorOf(int a, int N)
{
int k = 1;
if( a== N) return true; // 第一个判定过程 a=N?
if(a <= Math.floor(N/2)) { // 第二个判定过程 a<=[N/2]?符号限制原因用[]代替表示取整
for(;k<=Math.floor(N/a);k++) // 迭代过程开始
{
if(N == k*a) // 第三个判定过程 ak=N?
{
return true; //迭代出口1,出口向外输出true
}
}
return false; // 迭代出口2, 向外输出 false
}
else
return false; //第二个判定过程的另外一个出口,false值
}
public static void show(Boolean result,int a, int N)
{
if(result == true)
System.out.println(a +" 是 " + N + " 的约数 ");
else
System.out.println(a + " 不是 " + N + "的约数");
}
}
到这里,我们的主要业务代码变成:
public static void main(String[] argv)
{
int input_testnumber =2; // 被测试的数a 初值化
int input_naturalnubmer =28; //自然数N 初值化
Boolean result; // 测试结果, true 或者 false
result = factorOf(input_testnumber, input_naturalnubmer); //
// 到此,算法图中所有的内容都完成了,现在展示一下结果。
//以下,这是展示结果用的
show(result,input_testnumber,input_naturalnubmer);
}
比之前短了许多,需要事先设置三个变量来保存,两个输入的整数值,一个输出结果的Boolean值;
整个流程就是,先手动设置一下要进行测试的整数,再点击一下程序运行,这个主程序自动打出判决结果,这样的流程显然不具备效率,所以输入端还需要改一下,程序至少是半自动的,循环的。
我们修改一下输入:
import java.util.Scanner;
public class factor {
public static void main(String[] argv)
{
while(true) {
Scanner input = new Scanner(System.in);
int input_testnumber = input.nextInt(); // 被测试的数a 初值化
int input_naturalnubmer = input.nextInt(); //自然数N 初值化
Boolean result; // 测试结果, true 或者 false
result = factorOf(input_testnumber, input_naturalnubmer); //
// 到此,算法图中所有的内容都完成了,现在展示一下结果。
//以下,这是展示结果用的
show(result, input_testnumber, input_naturalnubmer);
}
}
public static Boolean factorOf(int a, int N)
{
int k = 1;
if( a== N) return true; // 第一个判定过程 a=N?
if(a <= Math.floor(N/2)) { // 第二个判定过程 a<=[N/2]?
for(;k<=Math.floor(N/a);k++) // 迭代过程开始
{
if(N == k*a) // 第三个判定过程 ak=N?
{
return true; //迭代出口1,出口向外输出true
}
}
return false; // 迭代出口2, 向外输出 false
}
else
return false; //第二个判定过程的另外一个出口,false值
}
public static void show(Boolean result,int a, int N)
{
if(result == true)
System.out.println(a +" is a factor of " + N);
else
System.out.println(a + " is not a factor of "+ N );
}
}
主要修改地方是在业务逻辑里面,即main()函数里面,加了一层循环,每次循环里面,用Scanner类从键盘等输入里面读取整数。
23 2
23 is not a factor of 2
23 24
23 is not a factor of 24
23 46
23 is a factor of 46
1 90
1 is a factor of 90
4 60
4 is a factor of 60
2 28
2 is a factor of 28
这是运行结果,可是,这个程序没法自己终结,因为加了一层永真循环,只能强制手动结束,而且每次输入都是手动交互输入。
但是值得注意的是,这一层是输入,可以随时修改,无论修改成系统的标准输入,或者做成文件输入(从txt文件读取,从二进制文件读取..),或者修改成随机过程生成,输入这段只要保证最后的两个量被转化成int值,就能接着进行接下来正确的判断。
整个程序被分成三段:
输入---> 判断---> 展示结果
任何一段都能够单独修改,
输入这一段要求产出2个int值;
判断这一段消费2个int值,产生一个Boolean值;
展示结果这一段消费一个Boolean值,来影响标准输出。
如果这一段程序被一个循环包着,就能半自动实现输入2个整数,判断这第一个是否是第二个的约数这一件事情。

浙公网安备 33010602011771号