我正在自学Java,所以我正在加州大学伯克利分校实验CS 61B。我正在尝试编写一个gcd方法来使我的toString方法有效。
toString方法以非缩小形式打印Fraction。 检查toString方法中的代码。它正在调用另一种方法 计算两个正整数的最大公约数(GCD)的gcd。 如果此方法正常工作,toString将以减少的方式打印分数 形成。我必须重写gcd的主体,以便它 一个正确计算GCD的递归函数。
这是我的toString方法:
public String toString() {
int thisGcd = gcd(numerator, denominator);
return (numerator / thisGcd + "/" + denominator / thisGcd);
}
我的目标是编写正确的gcd函数,以便toString以不可缩减的形式返回一个fracyion。这是我写的:
private static int gcd(int x, int y) {
int div;
if(x<0 || y<0){
return -1;
}
else {
if(x>y){
div = y ;
}
else{
div = x;
}
while( div !=0){
if( (x % div==0 )&&(y % div == 0) ) {
return div;
}
div --;
}
}
}
说明是关于使用以下伪代码编写递归gcd函数,但我不确定如何完全实现它:
function gcd(a, b)
if b = 0
return a
else
return gcd(b, a mod b)
我的gcd功能有什么问题?我如何让我的工作?我将如何编写递归函数?
答案 0 :(得分:7)
为什么不遵循说明?
private static int gcd(int x, int y) {
if (y == 0) {
return x;
}
return gcd(y, x % y);
}
此函数称为尾递归,因为最后一行是递归调用。尾递归函数很容易转换为while循环:
private static int gcd(int x, int y) {
while (y != 0) {
int tempX = x;
x = y;
y = tempX % y;
}
return x;
}
正如您所看到的,转换使得while循环谓词等于谓词来调用递归函数,而while循环的内容只是将x和y设置为与递归函数的输入相同。这一般是正确的(见wiki article)。
答案 1 :(得分:2)
递归函数:
public int gcd(int a, int b)
{
if(b == 0) return a;
else return gcd(b, a % b);
}
答案 2 :(得分:1)
以下是两个版本,一个简洁明了:
public static int gcd(int a, int b){
return b == 0 ? a : gcd(b, a % b);
}
另一个更接近你的指示:
public static int gcd(int a, int b) {
if (b == 0)
return a;
else
return gcd(b, a % b);
}
您的代码来自哪里?它看起来不像说明书。
这两个版本在语义上完全相同(我怀疑一秒钟,因为三元运算符具有自动装箱的奇怪行为......但是这里没有自动装箱的地方):
public static int gcd(int, int);
Code:
0: iload_1
1: ifne 8
4: iload_0
5: goto 15
8: iload_1
9: iload_0
10: iload_1
11: irem
12: invokestatic #10 // Method gcd:(II)I
15: ireturn
public static int gcd_verbose(int, int);
Code:
0: iload_1
1: ifne 6
4: iload_0
5: ireturn
6: iload_1
7: iload_0
8: iload_1
9: irem
10: invokestatic #13 // Method gcd_verbose:(II)I
13: ireturn
答案 3 :(得分:1)
你的gcd
效率很低。除此之外,它错过了最终的回报声明。假设您的输入为x
= 0且y
= 1.它将通过第一次检查输入&lt; 0,&#39; div&#39;是0并且永远不会执行while循环。现在,您在方法的最后没有任何return
语句。对于递归:
public int gcd(int a , int b){
return (b == 0 ? a : gcd(b , a % b));
}
答案 4 :(得分:0)
你问了三个问题:
其他人很好地回答了最后一部分,所以我不回答那个部分,而是关于你的另外两个问题:我的gcd功能有什么问题?我如何让我的工作?如何 我会写递归函数吗?
我的gcd功能出了什么问题?
第一件事是你的代码没有在每个状态都返回,虽然逻辑确实如此,但java会给你编译错误error: missing return statement
所以如果你只是想要你需要在函数末尾添加一个返回值它工作。但这不能解决您的问题,您的解决方案没有为gcd(0,a) = a
返回正确的值来解决此问题,您只需要进行一些更改!
我如何让我的工作?
这部分是关于进行更改,以下功能最接近您的答案,将正常工作:
private static int gcd(int x, int y) {
int div;
if(x<0 || y<0){
return -1;
}
else {
if(x>y){
div = x-y ; //to fix the problem for zero input
}
else{
div = y-x; //to fix the problem for zero input
}
while( div !=0){
if( (x % div==0 )&&(y % div == 0) ) {
return div;
}
div --;
}
return div; //the return statement so you dont get compile error and fix problem of zero input.
}
}
但为何停在那里?你的功能根本没有时间效率,所以我们做一些改变:
private static int gcd(int x, int y) {
int div;
int a;
if(x<0 || y<0){
return -1;
}
else {
if(x>y){
div = y;
a = x-y ;
}
else{
div = x;
a = y-x;
}
while( div !=0){
if( (x % div==0 )&&(y % div == 0) ) {
return div;
}
a = a - div;
if(a<div){
int temp = div;
div = a;
a = temp;
}
}
return a;
}
}
虽然这不是我想要的,但它是代码中最有效的代码。