Php 查找2个以上整数的GCD(最大公约数)?
我已经有一个函数可以找到2个数字的GCDPhp 查找2个以上整数的GCD(最大公约数)?,php,math,greatest-common-divisor,Php,Math,Greatest Common Divisor,我已经有一个函数可以找到2个数字的GCD function getGCDBetween($a, $b) { while ($b != 0) { $m = $a % $b; $a = $b; $b = $m; } return $a; } 但是现在,我想扩展这个函数,找到N个点的GCD。有什么建议吗?你可以试试 function gcd($a, $b) { if ($a == 0 || $b == 0)
function getGCDBetween($a, $b)
{
while ($b != 0)
{
$m = $a % $b;
$a = $b;
$b = $m;
}
return $a;
}
但是现在,我想扩展这个函数,找到N个点的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) 在每个数组中查找较大的整数
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
函数getAllDivisorsOf($n)
{
$sqrt=sqrt($n);
$除数=数组(1,$n);
对于($i=2;($i<$sqrt);$i++)
{
如果($n%$i)==0)
{
$divisors[]=$i;
$divisors[]=($n/$i);
}
}
如果(($i*$i)=$n)
{
$divisors[]=$i;
}
排序($除数);
返回$除数;
}
函数getGCDFromNumberSet(数组$nArray)
{
$allDivisors=array();
foreach($n美元)
{
$allDivisors[]=getAllDivisorsOf($n);
}
$allValues=array_unique(调用_user_func_array('array_merge',$allDivisors));
数组_unshift($allDivisors,$allValues);
$commons=call\u user\u func\u数组('array\u intersect',$allDivisors);
排序($commons);
返回端($commons);
}
echo getGCDFromNumberSet(数组(501001502004008001000));//50
有更好的主意吗?您可以将数字存储在数组和/或数据库中并从中读取。然后在一个循环中,你可以模块化地划分数组元素。取数字1和2的GCD,然后取数字1和数字3的GCD,依此类推。必须做一些挖掘,但是 三个数字的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;
}
函数多重GCD($nums)
{
$gcd=getGCDBetween($nums[0],$nums[1]);
对于($i=2;$i
有一种更优雅的方法:
// 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的方法
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);
}
是的,但只给出2个整数的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);
}