SPOILER
这是关于Project Euler的问题3,如果你想尝试它,请不要提前阅读,因为它包含答案!
所以我的目标是找到一个数字的最大素数因子,我写的代码就是这样,但是当数字变得很大而我无法理解为什么时会失败,我想知道是否有人可以查看我。我唯一能想到的是这个数字对于某些PHP的数据类型来说太大了吗?
我会粘贴我的代码,如果您没有本地测试环境,可以将代码粘贴到此处,http://writecodeonline.com/php/
理论(我确信有更有效的方法可以解决这个问题,但我既不是数学家也不是流利的编码员),它是从一个必须高于所有素数的数字开始的。因此,它然后按顺序尝试将起始数除以另一个数,如果结果是整数,则一次又一次地运行该过程,直到它不再给出整数(必须是一个素数因子)。然后它将起始数除以这个素数因子得到一个新数,然后它插回到第一个函数中以获得一个新的素数和另一个数,它一直这样做直到所有数字都是素数。然后有一个简单的检查最大的素数。
直到非常大的数字为止,即如果您使用13195
进行测试,则会将29
作为最大素数,但如果您使用600851475143
进行测试(问题)则会给出作为最大的素数是不对的。我知道答案是6857
,所以我确保我的起始计数器比它大但是它仍然失败 - 我无法理解为什么。
感谢您的时间,这里是代码(我知道会有更有效的方法,我想知道为什么我的工作不起作用。)
以下是代码:
$startVal = 13195;
echo "<b>Starting Value</b> = $startVal<br /><br />";
$scriptTime = -microtime(true);
$testVar = 10000;
$primeArray = array();
$processArray = "";
function findPrimes($startStart,$startTest, array & $primeArray, $processArray) {
$test = $startTest;
$start = $startStart;
$holdVal = NULL;
for ($i=$test; $i > 1 ; $i--) {
if(is_int($start/$i) && $start != $i) {
$processArray .= "$start is divisible by $i<br />";
$start = $i;
$i = $test +1;
}
}
$processArray .= "Can't Divide Further<br /><b>Found a Prime : <font color='red'>$start</font></b><br />";
$primeArray[] = $start;
if($start != $startStart) {
$holdVal = $startStart/$start;
}
if(isset($holdVal)) {
findPrimes($holdVal,$startTest,$primeArray,$processArray);
}
return array($primeArray,$processArray);
}
echo "Finding Primes...<br />";
$returnArray = findPrimes($startVal,$testVar,$primeArray,$processArray);
$primeArray = $returnArray[0];
$processArray = $returnArray[1];
echo "Script Found <b>".count($primeArray)."</b> Prime Numbers (";
for ($i=count($primeArray)-1; $i >= 0 ; $i--) {
if(!$i == 0)
echo $primeArray[$i].", ";
else
echo $primeArray[$i].")";
}
echo "<br />The largest Prime Factor of $startVal is <b><font color='red'>".max($primeArray)."</font></b><br />";
$scriptTime = round(($scriptTime += microtime(true))* 1000, 3);
echo "<i>Script took $scriptTime milliseconds<br />";
echo "<br /><br /><b>Process</b><br />";
echo "<pre>";
print_r($processArray);
echo "</pre>";
同样忽略进程文本位,我无法使其工作
答案 0 :(得分:3)
当你拥有32位机器时,数字600851475143超出了PHP中使用整数表示的范围,因此600851475143 / 6857
不是整数:
php> var_dump(600851475143/6857);
float(87625999)
如果使用BC任意精度库中的bcmod
实现可分性检查,则可以使其工作:
php> echo bcmod('600851475143','6857');
0
在您的代码中:
for ($i=$test; $i > 1 ; $i--) {
if(bcmod($start, $i) == 0 && $start != $i) {
$processArray .= "$start is divisible by $i<br />";
$start = $i;
$i = $test +1;
}
}
答案 1 :(得分:2)
我怀疑你遇到整数溢出。目标编号600851475143专门选择为不适合32位整数,因此该问题充当其他问题的“网关”,这些问题也需要大整数。解决方案是使用更大的数值数据类型。
答案 2 :(得分:1)
也许PHP是为32位编译的。 64位操作系统将很乐意运行32位二进制文件。转到http://php.net/manual/en/install.windows.manual.php并确保安装了64位二进制文件。