[英]PHP, Generating Primes, What's Wrong
這怎么了 條件語句看起來足夠扎實,但所有數字都包括在內
function generate_primes(){
$max = 100;
$primes = array();
for($current_pointer = 1; $current_pointer <= $max; $current_pointer++){
for($divider = 1; $divider <= $current_pointer; $divider++){
//if(in_array($divider, $primes)){
if(($current_pointer % $divider === 0) && ($divider !== 1) && ($divider === $current_pointer)){
$primes[] = $current_pointer;
}
//}
}
}
print_r($primes);
}
generate_primes();
重新考慮您的算法。 質數是大於1的自然數,除了自身和1之外,不能被其他任何自然數均分 。 因此,如果$current_pointer % $divider === 0
,則該數字不能是質數,因為它可以被$divider
整除。 那么,為什么要將它添加到數組中呢?
編輯以回應評論:為了明確起見,這意味着您必須檢查所有可能的除數(從2到數字本身為-1),並確保沒有一個除數可以除以有余數。 在這種情況下 ,數字是質數。
您可以稍微優化此算法(即,數字的根可以是內部循環的上限),但是首先請嘗試使這種情況在基本情況下起作用。
您需要處理分頻器確實將均分到current_pointer的情況,但該分頻器不等於當前指針。 在這種情況下,您需要跳出循環(即,您發現了均分的東西,因此數字不是素數)。 如所寫,所有循環最終都會碰到將數字自己除的情況,因此所有數字都會成功。
換句話說,您正在嘗試測試第一個成功的分頻器是數字本身,但是要做到這一點,當您碰到另一個成功的分頻器時,您必須停止嘗試。
if(($current_pointer % $divider === 0) && ($divider !== 1)){
if ($divider === $current_pointer)
$primes[] = $current_pointer;
} else {
continue; // the continue makes you stop testing the current pointer and go on to the next
}
我相信您的最后一個條件應該是:
$divider !== $current_pointer
兩件錯誤的事情:1) $divider === $current_pointer)
應該是$divider != $current_pointer)
和2)每次迭代后,您要將數字加到$ primes數組中。
建議:1)從2開始第二個循環,因為您希望$ divider不在第一位,並且2)使$ divider <$ current_pointer(而不是<=),因為您也希望$ divider不成為本身。
嘗試這個:
function generate_primes(){
$max = 100;
$primes = array();
for($current_pointer = 1; $current_pointer <= $max; $current_pointer++){
$prime = true;
for($divider = 2; $divider < $current_pointer; $divider++){
if($current_pointer % $divider == 0) $prime = false;
}
if($prime == true) array_push($primes, $current_pointer);
}
print_r($primes);
}
generate_primes();
首先,您的循環有點有趣;)如果要排除1,請不要以1開頭
其次,我不了解您的條件句的最后一條。 您說的是,僅當分隔符===指向當前指針時,才將其視為質數。 我認為您的意思是==指向當前指針。
查看您的if語句。 它基本上說:
在以下情況下,將數字標記為質數:
這些條件中的所有3個條件唯一的一次是最終條件為true時(除法器等於current_pointer。)
如果當前指針為6,則當分頻器等於6時,會將其存儲為質數(顯然不正確)。
將此示例視為一個簡單的(盡管實現起來很昂貴)函數,用於測試數字是否為質數(您可以輕松地使用該邏輯生成一個生成器。)
素數檢查器
問題是
if( ($current_pointer % $divider === 0) &&
($divider !== 1) &&
($divider === $current_pointer)){
當$divider == $current_pointer
時將始終為true
更好的方法是使用is_prime
標志初始化為true。 如果任何小於它的數字除以它,則將其設置為false。
進一步的增強是將數字二相加,然后僅檢查非偶數。
function generate_primes($max = 100){
$primes = array(2);
for($current_pointer = 3; $current_pointer <= $max; $current_pointer += 2){
if(is_odd_number_a_prime($current_pointer)){
$primes[] = $current_pointer;
}
print_r($primes);
return $primes
}
function is_odd_number_a_prime($n){
if(is_int($n)){
for($divider = 3; $divider < $n; $divider +=2 ){
if($current_pointer % $n == 0){
return false;
}
}
}else{
return false;
}
return true;
}
$primes = generate_primes();
您可以使用篩子進一步增強功能。
我建議您查找Eratosthene算法的篩網。 它用於獲取素數列表,並且與您采用的強力方法相比非常快。 雖然您的代碼可以在較小的數字上正常運行,但是您會發現,例如,嘗試使所有素數均小於10,000,000會花費很長時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.