问题描述
我为Greatest Common Divisor- GCD编写了此代码。 我从较大的整数中减去较小的整数,然后从最大的整数中减去较小的整数,然后再次从较大的整数中减去较小的整数,直到两个整数相等为止。 我想知道这是否正确, 是否可以使其更简单? 谢谢。
public static void main(String[] args) {
int firstInteger=114,secondInteger=67;
if (firstInteger>secondInteger) {
int result=firstInteger-secondInteger;
while (firstInteger != secondInteger) {
if (secondInteger > result) {
firstInteger = secondInteger;
secondInteger = result;
result = firstInteger - secondInteger;
} else {
firstInteger = result;
result = firstInteger - secondInteger;
}
}
System.out.println(firstInteger);
}
else {
int result=secondInteger-firstInteger;
while (secondInteger!=firstInteger) {
if (firstInteger>result) {
secondInteger=firstInteger;
firstInteger=result;
result=secondInteger-firstInteger;
}
else {
secondInteger=result;
result=secondInteger-firstInteger;
}
}
System.out.println(secondInteger);
}
}
解决方法
态度是正确的,并且代码将按预期运行,但是,如果将0用作值firstInteger
或secondInteger
,它将失败(锁定为连续循环)。有符号整数值也是如此。如果它们出现,您将需要处理这些情况。
尽管对于要执行的任务来说,代码很长,但它确实可以工作。如果您使用不同的概念来处理任务,例如,可以利用Modulo(%)运算符(也称为 Remainder Operator )并执行除法形式来将其大大缩短看看是否有余数,而不是进行减法,并忽略以哪个较大的参数值开头。这是一个实际上可以用作方法的示例:
public static int getGreatestCommonDivisor(int numerator,int denominator) {
if (numerator <= 0 || denominator <= 0) {
System.err.println("getGreatestCommonDivisor() Method Error! A value of "
+ "zero (0) or less can not be supplied as an argument!");
return -1;
}
int temp = numerator % denominator;
while (temp > 0) {
numerator = denominator;
denominator = temp;
temp = numerator % denominator;
}
return denominator;
}
如果要在方法内部处理带符号的参数值,则可以使用Math#abs()方法,该方法返回 int 值的绝对(正)值。此方法给出参数的绝对值。参数可以是int,double,long和float,但是对于此方法,我们只关心 int 类型的参数。这是一个示例:
public static int getGreatestCommonDivisor(final int numerator,final int denominator) {
if (numerator == 0 || denominator == 0) {
System.err.println("greatestCommonDivisor() Method Error! A value of "
+ "zero (0) can not be supplied as an argument!");
return -1;
}
int num = numerator;
num = Math.abs(numerator); // Ensure an absolute value
int gcd = Math.abs(denominator); // Ensure an absolute value
int temp = num % gcd;
while (temp > 0) {
num = gcd;
gcd = temp;
temp = num % gcd;
}
return gcd;
}
,
您的代码确实有效。下面是我编写的程序。
public int calculateGCD(int highNumber,int lowNumber){
boolean GCDFound = false;
int quotient,remainder,GCD = 1;
while(!GCDFound)
{
quotient = highNumber / lowNumber;
remainder = Math.floorMod(highNumber,lowNumber);
if(remainder == 0)
{
GCD = lowNumber;
GCDFound = true;
}
else
{
highNumber = lowNumber;
lowNumber = remainder;
}
}
return GCD;
}`
没有错误处理。数字既不为零也不为零。
我在您的(kamilP)代码和我的代码上完成了三个测试。每个测试使用1,000,000个数字对的二维数组。第一个数组编号在1到107,374,143之间,第二个数组编号在107,143和2,147,483,646之间,第三个数组编号在1和2,646之间。测试程序程序通过数组需要多长时间。
结果如下(以毫秒为单位): KamilP和CombatWomble
- 数组1273ms 155ms
- 数组2274ms 175ms
- 数组3285ms 173ms
这是我使其变得更简单,更快的方式。
,是否可以简化?
有几种方法可以简化它。这是三个。
- 第一种情况会修改您的算法。我没有进行性能分析,因为它需要诸如
JMH
之类的东西,但我尚未安装。 - 所有案例都处理正值和负值。
- 数学会自动调整分子和分母,因此调用方法时
r
和s
的顺序无关紧要。 - 第二种方法和第三种方法使用Euclids Algorithm
- 这两个方法都将在被0除时抛出异常。
在您的方法中,我使用了一个循环并更正了两个值 以确保在减法过程中取得积极结果。
public static int gcd(int r,int s) {
// absolute value of r and s
r = r > 0 ? r : -r;
s = s > 0 ? s : -s;
while (s > 0) {
// find min(r,s)
int t = r > s ? s : r;
// find max(r,s)
r = r > s ? r : s;
s = t;
r = r - s;
}
return r;
}
第二种方法是简单的迭代,可能是最有效的。但是,返回GCD之前必须更正该标志。
public static int gcd(int r,int s) {
while (s != 0) {
int t = r % s;
r = s;
s = t;
}
return r > 0 ? r : -r;
}
这是递归方法。再次需要纠正标志。
public static int gcd(int r,int s) {
if (s != 0) {
return gcd(s,r % s);
}
return r > 0 ? r : -r;
}
这里是对顺序和符号可能变化的测试。
System.out.println(gcd(24,36));
System.out.println(gcd(-24,36));
System.out.println(gcd(24,-36));
System.out.println(gcd(-24,-36));
System.out.println(gcd(36,24));
System.out.println(gcd(-36,-24));
System.out.println(gcd(36,-24));
System.out.println(gcd(-36,24));
所有三种方法都会打印。
12
12
12
12
12
12
12
12