Improved GCD() evaluation and additional tests
This commit is contained in:
parent
59326f1064
commit
19fd27811d
|
@ -312,6 +312,17 @@ class MathTrig
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function evaluateGCD($a, $b) {
|
||||||
|
// As we're just working with two values, we can use the recursive Euclidian method
|
||||||
|
// If we were working with more than two values, we need to extend as
|
||||||
|
// gcd(gcd(a, b), c)
|
||||||
|
// to encompass all the values we need to evaluate
|
||||||
|
// The method we're using is limited to integers, if we wanted to support floats as well
|
||||||
|
// then we'd need something like:
|
||||||
|
// return $b > .000000000001 ? gcd($b, fmod($a, $b)) : $a;
|
||||||
|
return $b ? self::evaluateGCD($b, $a % $b) : $a;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GCD.
|
* GCD.
|
||||||
*
|
*
|
||||||
|
@ -330,64 +341,22 @@ class MathTrig
|
||||||
*/
|
*/
|
||||||
public static function GCD(...$args)
|
public static function GCD(...$args)
|
||||||
{
|
{
|
||||||
$returnValue = 1;
|
$args = Functions::flattenArray($args);
|
||||||
$allValuesFactors = [];
|
|
||||||
// Loop through arguments
|
// Loop through arguments
|
||||||
foreach (Functions::flattenArray($args) as $value) {
|
foreach (Functions::flattenArray($args) as $value) {
|
||||||
if (!is_numeric($value)) {
|
if (!is_numeric($value)) {
|
||||||
return Functions::VALUE();
|
return Functions::VALUE();
|
||||||
} elseif ($value == 0) {
|
|
||||||
continue;
|
|
||||||
} elseif ($value < 0) {
|
} elseif ($value < 0) {
|
||||||
return Functions::NAN();
|
return Functions::NAN();
|
||||||
}
|
}
|
||||||
$myFactors = self::factors($value);
|
|
||||||
$myCountedFactors = array_count_values($myFactors);
|
|
||||||
$allValuesFactors[] = $myCountedFactors;
|
|
||||||
}
|
|
||||||
$allValuesCount = count($allValuesFactors);
|
|
||||||
if ($allValuesCount == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$mergedArray = $allValuesFactors[0];
|
$gcd = (int) array_pop($args);
|
||||||
for ($i = 1; $i < $allValuesCount; ++$i) {
|
do {
|
||||||
$mergedArray = array_intersect_key($mergedArray, $allValuesFactors[$i]);
|
$gcd = self::evaluateGCD($gcd, (int) array_pop($args));
|
||||||
}
|
} while (!empty($args));
|
||||||
$mergedArrayValues = count($mergedArray);
|
|
||||||
if ($mergedArrayValues == 0) {
|
|
||||||
return $returnValue;
|
|
||||||
} elseif ($mergedArrayValues > 1) {
|
|
||||||
foreach ($mergedArray as $mergedKey => $mergedValue) {
|
|
||||||
foreach ($allValuesFactors as $highestPowerTest) {
|
|
||||||
foreach ($highestPowerTest as $testKey => $testValue) {
|
|
||||||
if (($testKey == $mergedKey) && ($testValue < $mergedValue)) {
|
|
||||||
$mergedArray[$mergedKey] = $testValue;
|
|
||||||
$mergedValue = $testValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$returnValue = 1;
|
return $gcd;
|
||||||
foreach ($mergedArray as $key => $value) {
|
|
||||||
$returnValue *= pow($key, $value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnValue;
|
|
||||||
}
|
|
||||||
$keys = array_keys($mergedArray);
|
|
||||||
$key = $keys[0];
|
|
||||||
$value = $mergedArray[$key];
|
|
||||||
foreach ($allValuesFactors as $testValue) {
|
|
||||||
foreach ($testValue as $mergedKey => $mergedValue) {
|
|
||||||
if (($mergedKey == $key) && ($mergedValue < $value)) {
|
|
||||||
$value = $mergedValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pow($key, $value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -113,4 +113,20 @@ return [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
10.5,
|
||||||
|
2.6,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
4,
|
||||||
|
16.9,
|
||||||
|
12.1,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
13,
|
||||||
|
182,
|
||||||
|
481,
|
||||||
|
143,
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in New Issue