簡體   English   中英

PHP,生成素數,出了什么問題

[英]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語句。 它基本上說:

在以下情況下,將數字標記為質數:

  1. current_pointer等於0。
  2. 除法器不等於0。
  3. 分頻器等於current_pointer。

這些條件中的所有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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM