【问题标题】:Look for the GCD (greatest common divisor) of more than 2 integers?寻找超过 2 个整数的 GCD(最大公约数)?
【发布时间】:2012-12-11 20:30:24
【问题描述】:

我已经有一个函数可以找到 2 个数字的 GCD。

function getGCDBetween($a, $b)
{
    while ($b != 0)
    {
        $m = $a % $b;
        $a = $b;
        $b = $m;
    }
    return $a;
}

但是现在,我想扩展这个函数来找到 N 个点的 GCD。有什么建议吗?

【问题讨论】:

    标签: php math greatest-common-divisor


    【解决方案1】:

    有一种更优雅的方式来做到这一点:

    // Recursive function to compute gcd (euclidian method)
    function gcd ($a, $b) {
        return $b ? gcd($b, $a % $b) : $a;
    }
    // Then reduce any list of integer
    echo array_reduce(array(42, 56, 28), 'gcd'); // === 14
    

    如果您想使用浮点数,请使用近似值:

    function fgcd ($a, $b) {
        return $b > .01 ? fgcd($b, fmod($a, $b)) : $a; // using fmod
    }
    echo array_reduce(array(2.468, 3.7, 6.1699), 'fgcd'); // ~= 1.232
    

    您可以在 PHP 5.3 中使用闭包:

    $gcd = function ($a, $b) use (&$gcd) { return $b ? $gcd($b, $a % $b) : $a; };
    

    【讨论】:

      【解决方案2】:

      不得不做一些挖掘,但是this is what I found

      三个数的 gcd 可以计算为 gcd(a, b, c) = gcd(gcd(a, b)、c) 或以某种不同的方式通过应用交换性和 关联性。这可以扩展到任意数量的数字。

      你可以使用类似下面的东西:

      function multiGCD($nums)
      {
          $gcd = getGCDBetween($nums[0], $nums[1]);
      
          for ($i = 2; $i < count($nums); $i++) { $gcd = getGCDBetween($gcd, $nums[$i]); }
      
          return $gcd;
      }
      

      【讨论】:

        【解决方案3】:

        取数字 1 和 2 的 GCD,然后取那个和数字 3 的 GCD,以此类推。

        【讨论】:

          【解决方案4】:

          你可以试试

          function gcd($a, $b) {
              if ($a == 0 || $b == 0)
                  return abs(max(abs($a), abs($b)));
              $r = $a % $b;
              return ($r != 0) ? gcd($b, $r) : abs($b);
          }
          
          function gcd_array($array, $a = 0) {
              $b = array_pop($array);
              return ($b === null) ? (int) $a : gcd_array($array, gcd($a, $b));
          }
          
          echo gcd_array(array(50, 100, 150, 200, 400, 800, 1000)); // output 50
          

          【讨论】:

            【解决方案5】:

            我找到了一个解决方案,但它看起来有点难看:

            1) 检查每个整数的每个除数

            2) 找出每个数组中较大的整数

            function getAllDivisorsOf($n)
            {
                $sqrt = sqrt($n);
                $divisors = array (1, $n);
                for ($i = 2; ($i < $sqrt); $i++)
                {
                    if (($n % $i) == 0)
                    {
                        $divisors[] = $i;
                        $divisors[] = ($n / $i);
                    }
                }
                if (($i * $i) == $n)
                {
                    $divisors[] = $i;
                }
                sort($divisors);
                return $divisors;
            }
            
            function getGCDFromNumberSet(array $nArray)
            {
                $allDivisors = array ();
                foreach ($nArray as $n)
                {
                    $allDivisors[] = getAllDivisorsOf($n);
                }
                $allValues = array_unique(call_user_func_array('array_merge', $allDivisors));
                array_unshift($allDivisors, $allValues);
                $commons = call_user_func_array('array_intersect', $allDivisors);
                sort($commons);
                return end($commons);
            }
            
            echo getGCDFromNumberSet(array(50, 100, 150, 200, 400, 800, 1000)); // 50
            

            有更好的主意吗?

            【讨论】:

              【解决方案6】:

              您也可以使用gmp 库:

              <?php
                  $gcd = gmp_gcd( '12', '21' );
                  echo gmp_strval( $gcd );
              ?>
              

              【讨论】:

              • 是的,但是只给你 2 个整数的 GCD。
              【解决方案7】:

              您可以将数字存储在数组和/或数据库中并从那里读取。然后在一个循环中,您可以对数组元素进行模块化划分。

              【讨论】:

                【解决方案8】:

                我发现这在某处通过递归计算 gcd

                function gcd(...$numbers) {
                   if (count($numbers) > 2) {
                        return array_reduce($numbers, 'gcd'); // use php's array reduce
                  }
                
                  $r = $numbers[0] % $numbers[1];
                    return $r === 0 ? abs($numbers[1]) : gcd($numbers[1], $r);
                }
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-04-05
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-03-16
                  • 1970-01-01
                  • 2022-11-27
                  相关资源
                  最近更新 更多