我已经有一个函数可以找到两个数字的最大公约数。
function getGCDBetween($a, $b)
{
while ($b != 0)
{
$m = $a % $b;
$a = $b;
$b = $m;
}
return $a;
}
但是现在,我想将此函数扩展为查找N个点的最大公约数。有什么建议吗?
我已经有一个函数可以找到两个数字的最大公约数。
function getGCDBetween($a, $b)
{
while ($b != 0)
{
$m = $a % $b;
$a = $b;
$b = $m;
}
return $a;
}
有一种更为优雅的方法来实现这个:
// 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; };
您可以使用类似以下的方式:三个数的最大公约数可以计算为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;
}
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
取数字1和2的最大公约数,然后取该值与数字3的最大公约数,以此类推。
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
有更好的想法吗?
你可以将数字存储在数组和/或数据库中,并从那里读取。然后,你可以在循环内对数组元素进行模除运算。
我在某个地方找到了这个使用递归计算最大公约数的程序
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);
}