检查Scala中的数字是否为素数

时间:2016-04-27 06:35:36

标签: scala

我想检查数字是否为素数。我编写了以下代码,但它没有返回任何值:

 def isprime(x:Int) = {
     | if (x==1) false
     | else {
     | for (i <- 2 to x-1) {
     | if (x % i == 0) false
     | else true
     | }
     | }
     | }

12 个答案:

答案 0 :(得分:6)

你所做的是一个叫做定义一个函数,所以显然它不会返回任何东西,事实上,这个函数会返回AnyVal,这显然对你没什么帮助。我怀疑你确实需要返回一个布尔类型。

由于您正在使用REPL,因此您需要定义函数以检查数字是否为素数。我把它称为isPrime2,然后测试它。

def isPrime2(i :Int) : Boolean = {
|     if (i <= 1)
|       false
|     else if (i == 2)
|       true
|     else
|       !(2 to (i-1)).exists(x => i % x == 0)
|   }
// isPrime2: (i: Int)Boolean

(1 to 10).foreach(i => if (isPrime2(i)) println("%d is prime.".format(i)))
// 2 is prime.
// 3 is prime.
// 5 is prime.
// 7 is prime.

如果你不在使用if else条件,我甚至会建议一个更简单的版本:

def isPrime1(n: Int): Boolean = ! ((2 until n-1) exists (n % _ == 0))

这也返回一个布尔值。

编辑:

正如@TheArchetypalPaul所述,这也暗示了,问题是你的for循环没有产生任何值 - 你计算一个真/假值,但后来不做任何事情。所以你的else子句不会产生任何值(事实上,它产生Unit)。一旦找到除数,就需要返回false - 并且这样做的方式可能存在于isPrime1中。

答案 1 :(得分:4)

单线解决方案

def isPrime(num:Int):Boolean =
(num > 1) && !(2 to scala.math.sqrt(num).toInt).exists(x =>num % x == 0)

答案 2 :(得分:2)

这是另一个班轮:

def isPrime(num: Int): Boolean = (2 to num) forall (x => num % x != 0)

forall将检查谓词是否适用于此范围的所有元素

我刚刚意识到上面的代码对于更大的数字来说有点慢,所以这里有一个改进的版本:

def isPrime(n: Int): Boolean = (2 to math.sqrt(n).toInt) forall (x => n % x != 0)

答案 3 :(得分:1)

这可以是一种解决方案。

def isPrime(integer: Int): Boolean = {
   if (integer == 1) false
   else {
      val domain = (2 to math.sqrt(integer).toInt).view
      val range = domain filter (isDivisibleBy(integer, _))
      range.isEmpty
   }
}

def isDivisibleBy(integer: Int, divisor: Int): Boolean = integer % divisor == 0

现在回到您编写的代码,您的代码返回 AnyVal ,所需的返回类型应为布尔值。其背后的原因是Scala(或任何函数式语言)for循环是表达式而不是控制结构

答案 4 :(得分:1)

这是另外一个解决方案:

def isPrime(n: Int) = Range(2, n-1).filter(i => n % i == 0).length == 0 

甚至更短:

def isPrime(n: Int) = Range(2, n-1).filter(n % _ == 0).length == 0

答案 5 :(得分:1)

评论前面的答案(@jwvh除外):无需重复使用偶数。经过2的测试后,必须使用域3 to math.sqrt(integer).toInt by 2

我开发了一个加速的尾递归版本。它会跳过偶数个值,并一次性测试两个值。

import scala.annotation.tailrec
import scala.collection.immutable.TreeSet
import scala.compat.Platform
import scala.io.Source

object PrimesTestery extends App {
  val oeisPrimes = TreeSet(oeisPrimesText.map(_.toInt): _*)

  def rawText = Source.fromURL("https://oeis.org/A000040/a000040.txt")

  def oeisPrimesText = rawText.getLines.takeWhile(_.nonEmpty).map(_.split(" ")(1)).toList

  def isPrime(n: Long) = {
    val end = math.sqrt(n).toInt

    @tailrec
    def inner(d: Int): Boolean = {
      if (d > end) true
      else if (n % d != 0 && n % (d + 2) != 0) inner(d + 6) else false
    }

    n > 1 && ((n & 1) != 0 || n == 2) && (n % 3 != 0 || n == 3) && inner(5)
  }

  println(s"Found ${oeisPrimes.size} primes on OEIS , last is ${oeisPrimes.last}.")
  for (i <- (0 to oeisPrimes.last).par)
    assert(isPrime(i) == oeisPrimes.contains(i), s"Wrong $i")
  println(s"✔ Successfully completed without errors. [total ${Platform.currentTime - executionStart} ms]")

}

可以肯定的是,此代码针对素数和复合数字的素数列表进行了测试。

答案 6 :(得分:1)

该问题答案中的许多解决方案似乎要么行不通,要么没有涵盖明显的极端情况,要么公然效率低下。

下面是我的答案,该答案有效,涵盖了所有极端情况并且很有效,因为可能会出现在此特定领域中;也就是说,它会检查尽可能少的值,如果数字不是素数,则会尽早失败。

def isPrime(long: Long): Boolean =
  if (long > 8L) {
    !(((long % 2L) == 0L)
      || (3L to math.sqrt(long).toLong by 2L).exists(n => (long % n) == 0L))
  } else
    (long > 1L) && ((long == 2L) || ((long % 2L) != 0L))

答案 7 :(得分:1)

这一款不如一种衬垫优雅,但速度更快。它利用以下事实:所有质数(2和3除外)必须位于6k±1处。因此,它将跳过可被2或3划分的测试数字。它将仅测试(5,7),(11,13),(17,19)等组。

def isPrime(number: Int): Boolean =
  if (number < 4) number > 1
  else if (number % 2 == 0 || number % 3 == 0) false
  else (5 to math.sqrt(number).toInt by 6).forall(i => number % i != 0 && number % (i + 2) != 0)

答案 8 :(得分:0)

您还可以使用此递归函数:

med.out<- (med.fit, out.fit, treat="condition type", mediator = "shared oppression", robustSE = TRUE, sims = 100)

答案 9 :(得分:0)

这对于负数和大数也适用。 素数从2、3、5 ...

def isPrime(n: Int): Boolean = (n > 1) && ! Range(2, n-1).exists(n % _ == 0)

@tailrec
def isPrime(n: Int): Boolean = {
   def isPrimeTailrec(divisor: Int): Boolean = {
     if(divisor > Math.sqrt(Math.abs(n))) true
       else n % divisor != 0 && isPrimeTailrec(divisor + 1)
     }
     if(n < 2) false
     else isPrimeTailrec(2)
   }
}

答案 10 :(得分:-1)

def primeNumber(范围:Int):单位= {

val primeNumbers: immutable.IndexedSeq[AnyVal] =

  for (number :Int <- 2 to range) yield{

    val isPrime = !Range(2, Math.sqrt(number).toInt).exists(x => number % x == 0)

    if(isPrime)  number
  }

for(prime <- primeNumbers) println(prime)

}

答案 11 :(得分:-1)

def isPrime(n: Int) = (2 until n) forall(x => n % x !=0)