[英]Computing gcd in Java
我正在自學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功能有什么問題? 我如何讓我的工作? 我將如何編寫遞歸函數?
為什么不遵循說明?
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設置為與遞歸函數的輸入相同。 這一般是正確的(參見維基文章 )。
遞歸函數:
public int gcd(int a, int b)
{
if(b == 0) return a;
else return gcd(b, a % b);
}
這里有兩個版本,一個簡潔明了:
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
你的gcd
效率很低。 除此之外,它缺少最終的回報聲明。 假設你的輸入是x
= 0和y
= 1.它將通過第一次檢查輸入<0,'div'是0並且永遠不會執行while循環。 現在你在方法的最后沒有任何return
語句。 對於遞歸:
public int gcd(int a , int b){
return (b == 0 ? a : gcd(b , a % b));
}
你問了一個三部分的問題:
我的gcd功能有什么問題? 我如何讓我的工作? 我將如何編寫遞歸函數?
其他人很好地回答了最后一部分,所以我不回答那個部分,但關於你的另外兩個問題:
我的gcd功能有什么問題?
第一件事是你的代碼沒有在每個狀態都返回,雖然邏輯上確實如此,但java會給你編譯錯誤error: missing return statement
所以如果你只是想讓它工作你需要在函數的末尾添加一個返回值。 但這不會解決你的問題,你的解決方案沒有為gcd(0,a) = a
返回一個正確的值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;
}
}
雖然它不是我想要的,但它是最有效的代碼,可以從你的代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.