计算两个以上值的最大公约数(GCD)

时间:2018-12-04 15:43:26

标签: c# .net vb.net math

在VB.NET或C#中,我希望能够动态地计算一个或多个值的最大公约数(GCD),而无需使用递归方法。

我以C#中的准则this解决方案来计算两个值的GCD。现在,我希望对该解决方案进行调整,以能够计算不确定的值量(一个或多个值包含在传递给下面的函数的值数组中)...

这是我目前所做的:

VB.NET(原始代码):

<DebuggerStepperBoundary>
Private Shared Function InternalGetGreatestCommonDivisor(ParamArray values As Integer()) As Integer

    ' Calculate GCD for 2 or more values...
    If (values.Length > 1) Then
        Do While Not values.Contains(0)
            For Each value As Integer In values
                Dim firstMaxValue As Integer = values.Max()
                Dim secondMaxValue As Integer = values.OrderByDescending(Function(int As Integer) int)(1)
                values(values.ToList.IndexOf(firstMaxValue)) = (firstMaxValue Mod secondMaxValue)
            Next value
        Loop

        Return If(values.Contains(0), values.Max(), values.Min())

    Else ' Calculate GCD for a single value...
        Return ...

    End If

End Function

C#(在线代码转换,我根本没有测试过):

[DebuggerStepperBoundary]
private static int InternalGetGreatestCommonDivisor(params int[] values)
{

    // Calculate GCD for 2 or more values...
    if (values.Length > 1)
    {
        while (!values.Contains(0))
        {
            foreach (int value in values)
            {
                int firstMaxValue = values.Max();
                int secondMaxValue = values.OrderByDescending((int @int) => @int).ElementAtOrDefault(1);
                values[values.ToList().IndexOf(firstMaxValue)] = (firstMaxValue % secondMaxValue);
            }
        }

        return (values.Contains(0) ? values.Max() : values.Min());

    }
    else // Calculate GCD for a single value...
    {
        return ...;

}

我知道将类型转换为List会影响大量值的整体性能,但最优先的事情是使该算法按预期工作,并最终对其进行优化/重构。

对于某些值的组合,我的适应效果正常,但对于其他值却不起作用。例如,在this在线GCD计算器中,如果我们输入以下值:{1920、1080、5000、1000、6800、5555}理论上的GCD为5,或者至少是该在线服务计算出的GCD ,但是我的算法返回15。

3 个答案:

答案 0 :(得分:1)

// pass all the values in array and call findGCD function
    int findGCD(int arr[], int n) 
    { 
        int gcd = arr[0]; 
        for (int i = 1; i < n; i++) {
            gcd = getGcd(arr[i], gcd); 
}

        return gcd; 
    } 

// check for gcd
int getGcd(int x, int y) 
    { 
        if (x == 0) 
            return y; 
        return gcd(y % x, x); 
    } 

答案 1 :(得分:0)

您可以使用Linq:

    static int GCD2(int a, int b){
        return b == 0 ? Math.Abs(a) : GCD2(b, a % b);
    }

    static int GCD(int[] numbers){
        return numbers.Aggregate(GCD2);
    } 

答案 2 :(得分:0)

您面临的问题是由于您太早离开内循环而造成的。仅检查一个值是否为0是不够的,因为实际上您必须检查除一个值之外的所有值是否都是0。

C#代码如下所示:

private static int InternalGetGreatestCommonDivisor(params int[] values)
{
    // Calculate GCD for 2 or more values...
    if (values.Length > 1)
    {
      while (values.Count(value => value > 0) != 1)
      {
          int firstMaxValue = values.Max();
          int secondMaxValue = values.OrderByDescending((int @int) => @int).ElementAtOrDefault(1);
          values[values.ToList().IndexOf(firstMaxValue)] = (firstMaxValue % secondMaxValue);
      }

      return values.Max();

    }
    else
    {
      // Calculate GCD for a single value...
    }

}

对于您的示例,代码返回5。恐怕我不能为您提供VB.NET代码的确切表示。