* Prime.php
<?php
/**
https://projecteuler.net/problem=3
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
*/
class Prime {
/** @var int */
private $value;
public function __construct(int $value) {
$this->value = $value;
}
public function isPrime(int $num) : bool {
if ($num===2||$num===3) {return true;}
// for x >=1, 6x,6x+1,6x+2,6x+3,6x+4,6x+5
// 6x+2,6x+3,6x+4 => 2(3x+1),3(2x+1),2(3x+2)
if ($num % 6 !== 1 && $num % 6 !== 5) {return false;}
for ($i = 5; $i * $i <= $num; $i += 6) {
if ($num % $i === 0 || $num % ($i+2) ===0) {
return false;
}
}
return true;
}
private static function modMul(int $a, int $b, int $mod) : int {
$res = 0;
while ($b > 0) {
if ($b & 1) {
$res = ($res + $a) % $mod;
}
$a = ($a << 1) % $mod;
$b >>= 1;
}
return $res;
}
private static function modPow(int $a, int $n, int $mod) : int {
$res = 1;
while ($n) {
if ($n & 1) {
$res = self::modMul($res, $a, $mod);
}
$a = self::modMul($a, $a, $mod);
$n >>= 1;
}
return $res;
}
public static function millerRabin(int $n, int $loop = 20) : bool {
if ($n===2) {return true;}
if ($n < 2 || !($n & 1))
return false;
$m = $n - 1;
$k = 0;
while (!($m & 1)) {
$k++;
$m >>= 1;
}
// Miller-Rabin测试的迭代次数 $loop = 20
while ($loop-- > 0) {
$a = rand(0, $n-2) + 1;
$x = self::modPow($a, $m, $n);
$y = 0;
for ($j = 0; $j < $k; $j++) {
$y = self::modMul($x, $x, $n);
if ($y === 1 && $x != 1 && $x != $n-1) {
return false;
}
$x = $y;
}
if ($y !== 1) {
return false;
}
}
return true;
}
public function getPrimeFactors() {
$factors = [];
if ($this->isPrime($this->value)) {
return [ $this->value ];
}
// echo $this->value.' is not a prime number'.PHP_EOL;
$last = ceil($this->value/2);
$v = $this->value;
for ($cur = 2; $cur <= $last && $cur <= $v; ) {
if ($v % $cur === 0) {
if ($this->isPrime($cur)) {
// echo $cur . PHP_EOL;
array_push($factors, $cur);
// echo implode(',', $factors) . PHP_EOL;
}
$v /= $cur;
} else {
$cur++;
}
}
return $factors;
}
}
// test:
// $ time php Prime.php
$prime = new Prime(600851475143);
$a = $prime->getPrimeFactors(); // [71, 839, 1471, 6857]
print_r($a);
echo $a[count($a)-1].PHP_EOL; // 6857
// 0.042s
* test
$ time php Prime.php
Array
(
[0] => 71
[1] => 839
[2] => 1471
[3] => 6857
)
6857
real 0m0.039s
user 0m0.020s
sys 0m0.010s
https://blog.csdn.net/ECNU_LZJ/article/details/72675595
https://blog.csdn.net/xxxxfengheheda/article/category/7995856