我已经有一个函数可以找到 2 个数字的 GCD。
function getGCDBetween($a, $b)
{
while ($b != 0)
{
$m = $a % $b;
$a = $b;
$b = $m;
}
return $a;
}
但是现在,我想扩展这个函数来找到 N 个点的 GCD。有什么建议吗?
我已经有一个函数可以找到 2 个数字的 GCD。
function getGCDBetween($a, $b)
{
while ($b != 0)
{
$m = $a % $b;
$a = $b;
$b = $m;
}
return $a;
}
但是现在,我想扩展这个函数来找到 N 个点的 GCD。有什么建议吗?
有一种更优雅的方法可以做到这一点:
// 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
如果要使用浮点数,请使用 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
您可以在 PHP 5.3 中使用闭包:
$gcd = function ($a, $b) use (&$gcd) { return $b ? $gcd($b, $a % $b) : $a; };
不得不做一些挖掘,但这是我发现的。
三个数的 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;
}
取数字 1 和 2 的 GCD,然后是那个和数字 3 的 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
您还可以使用gmp库:
<?php
$gcd = gmp_gcd( '12', '21' );
echo gmp_strval( $gcd );
?>
我找到了一个解决方案,但它看起来有点难看:
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
有更好的主意吗?
您可以将数字存储在数组和/或数据库中并从那里读取。然后在一个循环中,您可以模块化划分数组元素。
我发现这在某处通过递归计算 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);
}