我希望的目标: 我想知道如何在Java中模仿Mathematica的ExtendedGCD[...]
功能。有关该函数的信息可以在此处找到here,但为了完整起见,我将简要描述它。
例如,在Mathematica中:ExtendedGCD[550,420]
返回{10,{13,-17}}
,因为550和420的最大公约数是10,并且源自Bézout's定理的"Bezout系数"13和17满足恒等式13(550)-17(420)=10
。
这对于n>2
的整数也适用:ExtendedGCD[550,420,3515]
返回{5,{-4563, 5967, 1}}
,因为GCD为5,而"Bezout系数" -4563、5967和1满足-4563(550)+5967(420)+1(3515)=5
。
我目前能做的:我可以计算两个整数的GCD(不包括Bezout系数):
public static int getGcd(int x, int y)
{
if (x == 0)
return y;
return gcd(y % x, x);
}
我可以使用这个方法计算一个整数数组的最大公约数(不包括 Bezout 系数):
public static int findGCD(int arr[])
{
int gcd = arr[0];
for (int i = 1; i < arr.length; i++) {
gcd = getGcd(arr[i], gcd);
}
return gcd;
}
我可以独立地找到两个整数的最大公约数和贝祖等式系数:
public static int[] gcdWithBezout(int p, int q) {
if (q == 0)
return new int[] { p, 1, 0 };
int[] vals = gcdWithBezout(q, p % q);
int d = vals[0];
int a = vals[2];
int b = vals[1] - (p / q) * vals[2];
return new int[] { d, a, b };
}
我想要的: 简单来说,我希望扩展方法gcdWithBezout
,使其能够接受任意长度的整数数组,并输出该数组的最大公约数以及 Bezout 系数。
在提出问题之前我做了什么: 我花了很多时间尝试修改算法。我还花了很多时间在 Google 和 StackOverflow 上搜索和浏览课程讲义等东西,以寻找可以使用/修改的内容。我甚至下载并阅读了计算数学、数字论等课程的在线讲义等等。
我肯定已经尽了自己的努力。
我知道的: 我了解一点点:我知道 GCD(a,b,c)=GCD(a,GCD(b,c))
;我知道贝祖定理;我也知道如何(笨拙地)手动求解贝祖系数,以及中国剩余定理等。
编辑: 我还知道关于这篇文章以及下面得到赞同的非常(数学上)有洞见的答案。这些帮助我理解如何递归地可视化问题,但它并没有帮助我澄清我所遇到的数据结构不匹配等问题。
结论和具体问题: 有人能帮我从现有的代码到达我想要的结果吗?
编辑: 我提供的方法是使用Java编写的,我的最终目标也是如此;然而,我也接受并欣赏非Java语言的解决方案。我可以将其他语言适应我的需求!
{5,{-4563,5967,1}}
是一种解决方案,但它不是最佳解决方案。例如,更好的解决方案是{5,{-2,11,-1}}
。递归应用ExtendedGCD
的问题在于贝祖定理系数变得非常大。 - user3386109