问题
I already have a function that finds the GCD of 2 numbers.
function getGCDBetween($a, $b)
{
while ($b != 0)
{
$m = $a % $b;
$a = $b;
$b = $m;
}
return $a;
}
But now, I would like to extend this function to find the GCD of N points. Any suggestion ?
回答1:
There is a more elegant way to do this :
// 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
If you want to work with floating points, use approximation :
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
You can use a closure in PHP 5.3 :
$gcd = function ($a, $b) use (&$gcd) { return $b ? $gcd($b, $a % $b) : $a; };
回答2:
Had to do a bit of digging, but this is what I found.
The gcd of three numbers can be computed as gcd(a, b, c) = gcd(gcd(a, b), c), or in some different way by applying commutativity and associativity. This can be extended to any number of numbers.
You could use something like the following:
function multiGCD($nums)
{
$gcd = getGCDBetween($nums[0], $nums[1]);
for ($i = 2; $i < count($nums); $i++) { $gcd = getGCDBetween($gcd, $nums[$i]); }
return $gcd;
}
回答3:
Take the GCD of numbers 1 and 2, and then the GCD of that and number 3, and so on.
回答4:
You can try
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:
I found a solution but it looks a bit ugly :
1) checking for every divisor of each integer
2) find the greater integer in every arrays
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
Any better idea ?
回答6:
You can also use the gmp library:
<?php
$gcd = gmp_gcd( '12', '21' );
echo gmp_strval( $gcd );
?>
回答7:
You can store the numbers in an array and/or database and read from there. And then within a loop you can modular divide the array elements.
回答8:
I found this somewhere calculates gcd by recursion
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);
}
来源:https://stackoverflow.com/questions/13828011/look-for-the-gcd-greatest-common-divisor-of-more-than-2-integers