学过数据结构以后,感觉以前写的一些简单的程序中,大多用了比较原始(蛮力)的算法。
今天在浙大中国大学MOOC《程序设计入门——C语言》课程中,看到了最大公约数求解的一种新方法——辗转相除法。刚好可以拿来和之前的蛮力算法及欧几里得算法做个比较。
参考文章:
学以致用——Java源码——最大公约数计算的普通算法与欧几里得算法的比较(Greatest Common Divisor)
https://blog.csdn.net/hpdlzu80100/article/details/85228095
运行结果:
请输入第一个整数(输入-1退出):333333333 请输入第二个整数(输入-1退出):666666666 方法1:333333333和666666666的最大公约数为:333333333,共用时3765850951.000000纳秒 方法2:333333333和666666666的最大公约数为:333333333,共用时24474.000000纳秒 方法2的用时是方法1的0.0006498930% 方法3:333333333和666666666的最大公约数为:333333333,共用时5921.000000纳秒 方法3的用时是方法1的0.0001572287%
请输入第一个整数(输入-1退出):4444444444 请输入第二个整数(输入-1退出):8888888888 方法1:4444444444和8888888888的最大公约数为:4444444444,共用时49768119912.000000纳秒 方法2:4444444444和8888888888的最大公约数为:4444444444,共用时1184.000000纳秒 方法2的用时是方法1的0.0000023790% 方法3:4444444444和8888888888的最大公约数为:4444444444,共用时789.000000纳秒 方法3的用时是方法1的0.0000015854% |
结论:
蛮力算法、欧几里得算法及辗转相除法三种算法中,辗转相除法的执行效率最高!
代码如下:
package exercises.ch6Methods;
import java.util.*;
//JHTP Exercise 6.27 (Greatest Common Divisor)
//by pandenghuang@163.com
/**
*
*6.27 (Greatest Common Divisor) The greatest common divisor (GCD) of two integers is the
*largest integer that evenly divides each of the two numbers. Write a method gcd that
*returns the greatest common divisor of two integers. [Hint: You might want to use Euclid’s algorithm.
*You can find information about it at en.wikipedia.org/wiki/Euclidean_algorithm.] Incorporate the method
*into an application that reads two values from the user and displays the result.
*
*/
public class GreatedCommonDivisor {
//此算法基于本人2008年的求最大公约数的方法,https://blog.csdn.net/hpdlzu80100/article/details/2290499
public static long gcd1(long n1, long n2) {
long g = 0;
for(long i=1;i<=Math.min(n1,n2);i++)
{
if (n1 % i == 0 && n2 % i == 0)
g = i;
}
return g;
}
//此算法https://blog.csdn.net/jiaolipe/article/details/1476068,采用了Euclid’s algorithm(欧几里得算法)
private static long gcd2 (long num1, long num2){
while (num1 != num2)
{
if (num1 > num2)
num1 = num1 - num2;
else
num2 = num2 - num1;
}
return num1;
}
//辗转相除法,参考了浙江大学中国大学MOOC《程序设计入门——C语言》课程案例
private static long gcd3 (long num1, long num2){
long temp = 0;
//如果num2<=num1,交换两数
if(num2>num1) {
temp = num2;
num2 = num1;
num1 = temp;
}
//辗转相除法
while (num2 != 0)
{
temp = num1 % num2;
num1 = num2;
num2 = temp;
}
return num1;
}
public static void main(String args[]) {
long number1;
long number2;
long gcd1;
long gcd2;
long gcd3;
Scanner scan=new Scanner(System.in);
do {
System.out.printf("请输入第一个整数(输入-1退出):");
number1 = scan.nextLong();
if(number1 == -1)
{System.out.print("已退出程序。");
break;
}
System.out.printf("请输入第二个整数(输入-1退出):");
number2 = scan.nextLong();
if(number2 == -1)
{System.out.print("已退出程序。");
break;
}
long beginTime=System.nanoTime();
gcd1 = gcd1(number1, number2);
long endTime=System.nanoTime();
double duration1=(double)(endTime-beginTime);
System.out.printf("方法1:%d和%d的最大公约数为:%d,共用时%f纳秒%n", number1, number2, gcd1, duration1);
beginTime=System.nanoTime();
gcd2 = gcd2(number1, number2);
endTime=System.nanoTime();
double duration2=(double)(endTime-beginTime);
System.out.printf("方法2:%d和%d的最大公约数为:%d,共用时%f纳秒%n", number1, number2, gcd2, duration2);
System.out.printf("方法2的用时是方法1的%.10f%%%n", duration2/duration1 * 100);
beginTime=System.nanoTime();
gcd3 = gcd3(number1, number2);
endTime=System.nanoTime();
double duration3=(double)(endTime-beginTime);
System.out.printf("方法3:%d和%d的最大公约数为:%d,共用时%f纳秒%n", number1, number2, gcd3, duration3);
System.out.printf("方法3的用时是方法1的%.10f%%%n", duration3/duration1 * 100);
System.out.println();
} while (number1 != -1);
System.out.println("已退出程序。");
scan.close();
}
}