如何在Java中编写扩展欧几里德算法代码?

时间:2014-11-18 21:55:21

标签: java algorithm data-structures

我有一个问题,实际上需要对欧几里得算法有所了解。问题很简单。用户通过扫描仪给出int“First”和int“Second”数字。 我们需要找到他们最大的共同除数。比过程如下所述:

现在假设第一个数字是:42,第二个是:30 - 它们是由用户给出的。 -

int x,y;

(x * First)+(y * Second)= gcd(First,Second); // X ?你?

要查找GCD,您可以使用:gcd(First,Second);代码如下:

public static int gcd(int a, int b)    
    {    
        if(a == 0 || b == 0) return a+b; // base case   
        return gcd(b,a%b);    
    }    

样本输入:第一:24秒:48,输出应为x:( - 3)和y:2
样本输入:第一个:42秒:30,输出应为x:( - 2)和y:3
样本输入:第一个:35秒:05,输出应为x:(0)和y:1

 (x * First) + (y * Second) = gcd(First, Second); // How can we find x and y ? 

如果您能在java中显示解决方案代码,我将非常感谢,感谢您的检查!

3 个答案:

答案 0 :(得分:3)

扩展欧几里德算法在this Wikipedia article中描述。基本算法就像这样说明(维基百科文章看起来更好):

  

更准确地说,标准的欧几里德算法用a和b作为   输入,包括计算序列q 1 ,...,   q k 商和序列r 0 ,...,   r k + 1 剩余部分

     

r 0 = a
r 1 = b
...

  r i + 1 = r i-1 -q i r i 且0<   r i + 1 < | r i |
...

     

欧几里德分裂的主要特性是不平等   右边从r i-1 和唯一地定义r i + 1   [R <子> I

     

当一个到达余数r k + 1 时,计算停止   这是零;最大的公约数是最后的非零   余数r k

     

扩展的欧几里德算法类似地进行,但增加了两个   

定义的其他序列      

s 0 = 1,s 1 = 0
t 0 = 0,   t 1 = 1
...
  s i + 1 = s i-1 -q i s i
  t i + 1 = t i-1 -q i t i

这应该很容易在Java中实现,但它所表达的数学方式可能使其难以理解。我会试着把它分解。

请注意,这可能比在递归中更容易在循环中实现。

在标准欧几里得算法中,根据r i-1 和r i 计算r i + 1 。这意味着您必须保存以前版本的 r 。这部分公式:

  

r i + 1 = r i-1 -q i r i 且0&lt;   r i + 1 &lt; | r i |
...

只是意味着当r i-1 除以r i 时,r i + 1 将是余数。 q i 是商,你不在标准的欧几里德算法中使用,但你确实在扩展的算法中使用。因此,执行标准欧几里德算法(即计算GCD)的Java代码可能如下所示:

prevPrevR = a;
prevR = b;
while ([something]) {
    nextR = prevPrevR % prevR;
    quotient = prevPrevR / prevR;  // not used in the standard algorithm
    prevPrevR = prevR;
    prevR = nextR;
}

因此,在任何时候,prevPrevR基本上都是r i-1 ,而prevR将是r i 。该算法计算下一个 r ,r i + 1 ,然后将基本上递增 i 的所有内容移位1。

扩展的欧几里德算法将以相同的方式完成,保存两个 s prevPrevSprevS,以及两个 t 值{{ 1}}和prevPrevT。我会让你弄清楚细节。

答案 1 :(得分:1)

感谢帮助我解决问题我在挖掘你的答案后解决了这个问题。对于那些希望看到代码明智的人:

public class Main    
{    
public static void main (String args[])   
{   
    @SuppressWarnings("resource")    
    System.out.println("How many times you would like to try ?")
    Scanner read = new Scanner(System.in);    
    int len = read.nextInt();    

    for(int w = 0; w < len; w++)    
    {
        System.out.print("Please give the numbers seperated by space: ")
        read.nextLine();
        long tmp = read.nextLong();
        long m = read.nextLong();
        long n;
        if (m < tmp) {      
            n = m;
            m = tmp;
        }
        else {
            n = tmp;
        }

        long[] l1 = {m, 1, 0};
        long[] l2 = {n, 0, 1};
        long[] l3 = new long[3]; 

        while (l1[0]-l2[0]*(l1[0]/l2[0]) > 0) {
            for (int j=0;j<3;j++) l3[j] = l2[j]; 
            long q = l1[0]/l2[0];        
            for (int i = 0; i < 3; i++) {
            l2[i] = (l1[i]-l2[i]*q);
            }

            for (int k=0;k<3;k++) l1[k] = l3[k];
        }

        System.out.printf("%d %d %d",l2[1],l2[2],l2[0]); // first two Bezouts identity Last One gcd
    }
}
}    

答案 2 :(得分:-1)

以下是我想出的代码,如果有人还在寻找的话。它在C#中,但我确信它与java类似。享受

    static void Main(string[] args)
    {
        List<long> U = new List<long>();
        List<long> V = new List<long>();
        List<long> W = new List<long>();

        long a, b, d, x, y;

        Console.Write("Enter value for a: ");
        string firstInput = Console.ReadLine();
        long.TryParse(firstInput, out a);

        Console.Write("Enter value for b: ");
        string secondInput = Console.ReadLine();
        long.TryParse(secondInput, out b);

        long temp;
        //Make sure that a > b
        if(a < b)
        {
            temp = a;
            a = b;
            b = temp;
        }
        //Initialise List U
        U.Add(a);
        U.Add(1);
        U.Add(0);

        //Initialise List V
        V.Add(b);
        V.Add(0);
        V.Add(1);

       while(V[0] > 0)
        {
            decimal difference = U[0] / V[0];
            var roundedDown = Math.Floor(difference);
            long rounded = Convert.ToInt64(roundedDown);

            for (int i = 0; i < 3; i++)
                W.Add(U[i] - rounded * V[i]);

            U.Clear();
            for (int i = 0; i < 3; i++)
                U.Add(V[i]);

            V.Clear();
            for (int i = 0; i < 3; i++)
                V.Add(W[i]);

            W.Clear();

        }

       d = U[0];
       x = U[1];
       y = U[2];
       Console.WriteLine("\nd = {0}, x = {1}, y = {2}", d, x, y);

        //Check Equation
        Console.WriteLine("\nEquation check: d = ax + by\n");
        Console.WriteLine("\t{0} = {1}({2}) + {3}({4})", d, a, x, b, y);
        Console.WriteLine("\t{0} = {1} + {2}", d, a*x, b*y);
        Console.WriteLine("\t{0} = {1}", d, (a * x) + (b * y));
        if (d == (a * x) + (b * y))
            Console.WriteLine("\t***Equation is satisfied!***");   
        else
            Console.WriteLine("\tEquation is NOT satisfied!");
    }
}

}