【问题标题】:PHP - check if number is primePHP - 检查数字是否为素数
【发布时间】:2016-06-24 07:42:05
【问题描述】:

我正在尝试创建一个检查数字是否为素数的函数。但我希望这个函数回显给用户“prime”或“NOT prime”——这就是我的问题开始的地方。 让我给你看我的代码:

class IsPrime
{       
    function check($num)
    {
        for ($i = 2; $i < $num; $i++)
        {
            if ($num % $i == 0) 
            {
                echo 'NOT prime';
                break;
            }               
        }
        echo 'Prime';           
    }       
}

$x = new IsPrime();
$x->check(4);

问题是当我输入任何素数时 - 它可以正常工作,但是当我输入任何非素数时 - 它也会回显第二个回声,就像这样:'NOT prime prime'

我怎样才能让它只回显正确的答案?

【问题讨论】:

标签: php


【解决方案1】:

54 59 个字节中:

function is_prime($n){for($i=$n;--$i&&$n%$i;);return$i==1;}

$n-1 向下循环$i,直到找到$n 的除数;如果除数为 1,$n 是素数。


添加 10 个字节以获得更好的性能:

function is_prime($n){for($i=$n**.5|1;$i&&$n%$i--;);return!$i&&$n>1;}

循环 $i 从(大约)sqrt($n)1 寻找一个在 $i 上具有后减量的除数。
如果除数是1,则$i最后是0!$i给出true

这个解决方案使用了一个技巧:对于$n=23$i 将被初始化为 1 → 在第一次迭代中循环退出。对于更大的偶数平方根 ($n**.5|0),|1 用作+1。对于奇数平方根,不需要+1,因为:如果$n 可以被root+1 整除,那么它也可以被2 整除。不幸的是,这可能会花费大量迭代;所以你更好


再增加 7 个字节以获得更好的性能:

function is_prime($n){for($i=~-$n**.5|0;$i&&$n%$i--;);return!$i&$n>2|$n==2;}

$n=2 在这里需要一个特殊情况:初始$i=2 除以$n=2 → 最终$i=1 → 返回false

1 添加到$n 而不是平方根足以避免失败;但是:


我没有计算迭代次数,只测试了时间消耗;并且仅在二氧化钛而不是受控环境中。最后两个版本之间的差异小于几次运行之间的偏差。 稍后可能会添加重要的测试结果。

【讨论】:

  • 在 2106 年的解释器脚本语言中,你认为那些字节重要吗?它只会让您的代码对其他开发人员完全不可读。
  • @vaso123 为什么要浪费空间,因为你有很多?
  • 因为可读性是最重要的事情之一,比代码长度更重要。
  • 问题是“为什么我的代码回显两次?” (提示:休息而不是返回)。您为“如何编写缓慢而草率的代码来查找素数以节省一些脚本字节?”写了完美的答案。
  • @FrancescoMM 是的。这就是所谓的代码高尔夫。在某些方面仍然完美。 :D 但是对 OP 的完美答案是return,而不是exit,而不是break。 (请参阅 amin saffar 对第一个答案的评论。)
【解决方案2】:

如果这个数字真的是一个素数,这可能是一个很长的过程。还有一个较短的程序。 我们不需要将 for 循环运行到数字本身。相反,我们可以将其运行到小于或等于数字平方根的最高整数。

class IsPrime
{       
     function check($num)
     {
        $bCheck = True;


        $highestIntegralSquareRoot = floor(sqrt($num));
        for ($i = 2; $i <= $highestIntegralSquareRoot; $i++)
        {
            if ($num % $i == 0) 
            {
                 $bCheck = False;
                 break;
            }               
        }
       if $bCheck 
          echo 'Prime';           
       else
          echo 'NOT prime'; 
     }       
  }

 $x = new IsPrime();
 $x->check(97);

现在,在上面,如果我们检查 97 是否是素数(实际上是),那么循环不需要从 2 到 97,而只需从 2 到 9。(97 的平方根是9.8488578018,小于或等于9的最大整数是9。同样,我们可以检查数字121(这不是质数,因为它可以被11整除)。限制将在类似的情况下从2增加到11事。等等。 实际上,我们需要检查该数字是否可以被附近较小的素数整除,但这会更复杂。 希望这会有所帮助。

【讨论】:

    【解决方案3】:

    正如许多答案指出的那样,您的逻辑代码有一个问题:当您得到i 这样num % i == 0 时,您打印“NOT prime”并退出循环,之后,您仍然打印“Prime”。有些人把echo "Prime" 移到if-else 中,仍然是错误的。例如,一种接近的方法,

    class IsPrime
    {       
         function check($num)
         {
            $bCheck = True; 
            for ($i = 2; $i < $num; $i++)
            {
                if ($num % $i == 0) 
                {
                     $bCheck = False;
                     break;
                }               
            }
           if $bCheck 
              echo 'Prime';           
           else
              echo 'NOT prime'; 
         }       
      }
    
     $x = new IsPrime();
     $x->check(4);
    

    【讨论】:

      【解决方案4】:
      <?php
      function primeCheck($num)
      {
          if ($num == 1)
              return false;
              for ($i = 2; $i <= $num/2; $i++)
              {
                  if ($num % $i == 0)
                  {
                      return false;
                  }
              }
          return true;
      }
      
      $primeNumber = primeCheck(17);
      
      if ($primeNumber == true)
      {
          echo "Is Prime";
      }
      else
      {
          echo "Is Not Prime";
      }
      ?>
      

      【讨论】:

        【解决方案5】:

        break 只是打破 for 循环, 请改用return;。它会退出函数

        【讨论】:

        • 我在您的帖子发布前几分钟就发现了自己 - 但这是正确的答案。欢呼
        【解决方案6】:
        只需使用返回:
        class IsPrime
        {       
        function check($num)
        {
            for ($i = 2; $i < $num; $i++)
            {
                if ($num % $i == 0) 
                {
                    echo 'NOT prime';
                    return; // that you need
                }               
            }
            echo 'Prime';           
        }       
        }
        
        $x = new IsPrime();
        $x->check(4);
        

        if/else notation
        return notation

        【讨论】:

          【解决方案7】:

          您可以找到从 1 到您的极限及其计数的素数和非素数。

          public function prime_checker($count){
            $counter=0;
            $no_prime=0;
            for($i=2 ; $i<=$count; $i++ ){
              for($j=2 ; $j<$i ; $j++ ){
                if($i % $j == 0){
                  echo $i.'is not prime<br/>';
                  $no_prime=$i;
                  break;
                }
              }
              if($i != $no_prime){
                $prime_numbers[$counter]=$i;
                $counter=$counter+1;
              }    
            }
            echo '<br/>'.$counter.'prime numbers<br/><br/>';
            for($i=0 ; $i<$counter ; $i++ ){
              echo $prime_numbers[$i].' is  prime<br/>';
            }
          }
          

          【讨论】:

          • 请您在回答中添加解释
          • 你可以找到从 1 到你的极限的素数和非素数,还可以打印素数的个数
          • 这怎么可能是对原始问题的答复?问题是“为什么我的代码回显两次?”你回复了一些缓慢而草率的代码来列出所有素数......它只是属于其他地方。
          【解决方案8】:

          您可以在不使用循环的情况下检查数字是否为素数:

          function is_prime($p) {
          
              $r1 = $p%2;
              $r2 = $p%3;
              $r3 = $p%5;
          
              return ($p > 1) &&  (($r1 >= 1) && ($r2 >= 1) && ($r3 >= 1)) ||  in_array($p, [2,3,5]);
          }
          

          【讨论】:

          • 这根本不正确。 49(7*7)、77(7*11)、121(11*11)等返回true
          • 不能被 2、3 和 5 整除不会使数字成为质数!任何能被 7 或 11 或 13 整除的数呢?
          【解决方案9】:

          请检查一下

          class IsPrime
          {       
              function check($num)
              {
                  for ($i = 2; $i < $num; $i++)
                  {
                      if ($num % $i == 0) 
                      {
                          return 'NOT prime';
          
                      }
          
                  }
                  return 'Prime';           
              }       
          }
          
          $x = new IsPrime();
          $result = $x->check(4);
          echo $result;
          

          【讨论】:

            【解决方案10】:

            试试这个

            class IsPrime
            {       
            function check($num)
            {
                for ($i = 2; $i < $num; $i++)
                {
                    if ($num % $i == 0) 
                    {
                        echo 'NOT prime';
                        break;
                    }
                    else
                    {
                        echo 'Prime';
                    }
                }
                //echo 'Prime';           
            }       
            }
              $x = new IsPrime();
              $x->check(3);
            

            【讨论】:

            • 为什么要尝试?有什么意见吗?
            【解决方案11】:

            放置 else 部分,否则它总是return Prime

                for ($i = 2; $i < $num; $i++)
            {
                if ($num % $i == 0)
                {
                    echo 'NOT prime';
                    break;
                }
                echo 'Prime';
            }
            

            【讨论】:

              【解决方案12】:

              您可以打印“Prime”作为对函数的返回,以确保在函数期间除了“NOT prime”的条件外不打印任何内容。

                 class IsPrime
                  {       
                      function check($num)
                      {
                          for ($i = 2; $i < $num; $i++)
                          {
                              if ($num % $i == 0) 
                              {
                                  echo 'NOT prime';
                                  break;
                              }               
                          }
                        return "Prime";         
                      }       
                  }
              
                  $x = new IsPrime();
                  echo $x->check(4);
              

              【讨论】:

              • 如果使用 $x->check(3);它将被返回,而不是打印
              • 我在函数之前添加了一个回显,它将打印出“Prime”。但我想这个答案与这里的大多数答案相似。
              【解决方案13】:
              $num = ceil(sqrt($num));
              
              $is_prime = true;
              for($j=3; $j<=$num; $j=$j+2){
                  if($i%$j == 0){         
                      $is_prime = false;
                      break;
                  }
              }
              
              if($is_prime){
                  echo "No is Prime";
              }
              

              注意:从 2 开始循环,因为它是唯一的偶素数。以 2 递增作为 no 偶数是素数。

              => 查找 (2-100) 范围内所有素数的代码

              $limit = 100; $arr = array(2);
              for($i=3; $i<=$limit; $i=$i+2){
              
                  $num = ceil(sqrt($i));
              
                  $is_prime = true;
                  for($j=3; $j<=$num; $j=$j+2){
                      if($i%$j == 0){         
                          $is_prime = false;
                          break;
                      }
                  }
              
                  if($is_prime){
                      $arr[] = $i;
                  }
              }
              

              【讨论】:

                【解决方案14】:

                我做了一个类似的例子,用户输入一个数字,PHP 检查这个数字是否是素数。

                HTML

                <p>See if your number is a prime number</p>
                
                <form>
                
                <input type='number' name='number'>
                
                <input type='submit' value='Check!'>
                
                </form>
                

                PHP

                if ($_GET) {
                
                    $i = 2;
                
                    $isPrime = true;
                
                    while ($i < $_GET['number']) {
                
                        if ($_GET['number'] % $i == 0){
                
                            // Number is NOT prime
                            $isPrime = false;
                
                        }
                
                        $i++;
                    }
                
                    if ($isPrime){
                
                        echo '<p>'.$i.' is a prime number!';
                
                    } else {
                
                        echo '<p>'.$i.' is NOT a prime number';
                
                    }
                
                }
                

                希望这对你有用。

                【讨论】:

                  【解决方案15】:

                  首先,这里不要搞错:

                  for ($i = 2; $i < $num; $i++)
                  

                  然后:

                  if ($num % $i == 0) return false;
                  

                  2 % 2 等于 0,然后 2 将成为非素数。

                  接下来,您不必检查偶数,因此在检查 $num == 2 后,更好的性能是:

                  for ($i = 3; $i < $num/2; $i += 2)
                  

                  注意 $num/2 - 你不必检查超过这一点。 更好的是:

                  for ($i = 3; $i*$i <= $num; $i += 2)
                  

                  这是因为当您检查 2 和 3 的除法时,所有其他非素数都是两个(或更多)素数的乘积(例如 49 = 7*7 或 55 = 5*11)。在最坏的情况下,您的 $i 指针将达到 $num 的平方根(如 49 = 7*7)。这就是为什么你检查直到 $i*$i

                  【讨论】:

                    【解决方案16】:

                    整个程序是正确的。但只有你应该用 exit 函数替换 break 。因为 break 仅用于退出用花括号 {} 括起来的循环,而 exit 用于停止执行整个脚本。

                    class IsPrime
                    {   
                        function check($num)
                        {
                            for ($i = 2; $i < $num; $i++)
                            {
                                if ($num % $i == 0) 
                                {
                                    echo 'NOT prime';
                                    break;
                                }               
                            }
                            echo 'Prime';           
                        }       
                    }
                    
                    $x = new IsPrime();
                    $x->check(4);
                    

                    【讨论】:

                    • returnexit 好,因为我们在函数体中。
                    【解决方案17】:
                    function is_prime($number)
                    {
                        return (bool) !preg_match('/^1?$|^(11+?)\1+$/x', str_repeat('1', $number));
                    }
                    

                    【讨论】:

                    • 只是到处乱逛? :)
                    【解决方案18】:

                    这是我的解决方案。如果你把条件放在循环中并在它之后中断,它永远不会完成检查。

                    $num = rand ( 1, 1000 );
                    
                    $notPri = null;
                    
                    for($check = 2; $check < $num; $check ++) {
                    
                          if ($num % $check == 0) {
                              $notPri ++;
                             }
                           }
                    
                    if ($neEpri == 0) {
                    
                        echo $num . "<br>Prime!";
                    
                    } else {
                         echo $num . "<br>Not a prime!";
                       }
                    

                    【讨论】:

                      猜你喜欢
                      • 2013-03-22
                      • 1970-01-01
                      • 2015-09-15
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-11-14
                      相关资源
                      最近更新 更多