簡體   English   中英

用Java計算gcd

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM