6

I wanted to check if a number is prime or not. I wrote the following code, but it does not return any value:

 def isprime(x:Int) = {
     | if (x==1) false
     | else {
     | for (i <- 2 to x-1) {
     | if (x % i == 0) false
     | else true
     | }
     | }
     | }
Arnab
  • 1,037
  • 3
  • 16
  • 31
  • where are you running it ? and how are you running it ? – eliasah Apr 27 '16 at 06:37
  • you can get answer at this link : [http://stackoverflow.com/questions/9711785/find-prime-numbers-using-scala-help-me-to-improve](http://stackoverflow.com/questions/9711785/find-prime-numbers-using-scala-help-me-to-improve) – Alireza Izadimehr Apr 27 '16 at 06:38
  • I am using the Scala REPL – Arnab Apr 27 '16 at 06:38
  • @AlirezaIzadimehr I read that link, but I needed to use simple if-else statements to accomplish it – Arnab Apr 27 '16 at 06:40
  • Check the answer and accept it if it solves your problem ! – eliasah Apr 27 '16 at 06:49
  • 2
    I think the answers while not wrong are not really addressing the issue. Amab, the problem is that your for loop isn't resulting in any value - you calculate a true/false value, but then don't do anything with it. So your else clause doesn't result in any value (in fact, it produces `Unit`). You need to return false as soon as you find a divisor - and the way to do that is probably `exists` as in @eliasah's answer. – The Archetypal Paul Apr 27 '16 at 07:17
  • @TheArchetypalPaul I would like to add your comment into my answer, if that's ok with you. At some level, I thought that it was implied but it didn't seem to be. – eliasah Apr 27 '16 at 07:19

13 Answers13

10

What you did is a called defining a function so obviously it won't return anything and as a matter of fact, this function returns AnyVal which obviously won't help you much. I suspect that you actually need a Boolean type returned.

Since you are working with the REPL, you would want to define your function to check if a number is prime. I called it isPrime2 and then test it.

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.

I would even suggest a simpler version if you care not using if else conditions :

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

Which also returns a Boolean.

EDIT:

As @TheArchetypalPaul stated, which was also implied, the problem is that your for loop isn't resulting in any value - you calculate a true/false value, but then don't do anything with it. So your else clause doesn't result in any value (in fact, it produces Unit). You need to return false as soon as you find a divisor - and the way to do that is probably exists as in isPrime1.

eliasah
  • 39,588
  • 11
  • 124
  • 154
  • 7
    A further refinement suitable for large numbers: `def isPrime(n: Long): Boolean = !(2 +: (3 to Math.sqrt(n).toInt by 2) exists (n%_ == 0))` – jwvh Apr 27 '16 at 07:24
  • As shown in the comment by @jwvh there is no point in checking numbers higher than the square root of `n`. It's also nice that it skips the even numbers: no point in checking them all if you are checking `2` already. – Sim Jan 31 '17 at 03:00
  • 1
    @jwvh just noticed that your solution will return `true` for `1` as well as some negative numbers. You need an explicit check for that. – Sim Jan 31 '17 at 03:07
  • @Sim, correct. My solution was offered as a performance enhancement to the suggested "simpler version". The original's edge-case deficiencies were not addressed. – jwvh Feb 01 '17 at 17:02
  • I don't know about Amab, but for my application I need `isPrime(-47)` (for example) to return true. Of course it would take just a minor adjustment. – Alonso del Arte Jan 23 '20 at 16:39
8

One liner Solution

def isPrime(num:Int):Boolean =
(num > 1) && !(2 to scala.math.sqrt(num).toInt).exists(x => num % x == 0)
Mahesh Chand
  • 3,158
  • 19
  • 37
  • In the second line, I found any number from 1 to num/2, divides the given number. If yes that means it is not prime. For example, 10 -> It will check 2 to 3 and 2 will divide 10 so this is not prime. I just took the negation of the result to the second. – Mahesh Chand Mar 09 '21 at 10:06
4

Here is one more 1 line solution:

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

Or even shorter:

def isPrime(n: Int) = Range(2, n-1).filter(n % _ == 0).length == 0
Teimuraz
  • 8,795
  • 5
  • 35
  • 62
4

This one is less elegant than the one liners, but a bit faster. It uses the fact that all primes (except 2 and 3) have to be at 6k±1. So it skips testing numbers which are dividable by 2 or 3. It will only test for the groups of (5, 7), (11, 13), (17, 19) and so on.

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)
kanbagoly
  • 319
  • 3
  • 9
  • That's very clever. Tysvm for posting. I've just updated my answer to indicate yours is more efficient than mine. I also provided a conversion to `Long` as that is what I needed. And it is easy to trip up converting an `Int` implementation into a `Long` implementation. If you were to also provide a properly implemented `Long` version, I would be happy to remove my conversion and just point to your answer. – chaotic3quilibrium Sep 18 '19 at 17:08
3

Here is another one liner:

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

forall will check if the predicate holds for all elements of this range

I just realised that the code above is a bit slow for bigger numbers, so here an improved version:

def isPrime(n: Int): Boolean = (2 to math.sqrt(n).toInt) forall (x => n % x != 0)
TheQuestioner
  • 724
  • 2
  • 8
  • 13
3

Many of the solutions in the answers to this question appear to either not work, haven't covered obvious edge cases, and/or are blatantly inefficient.

Below is my answer which works, covers all edge cases, and is as efficient as it is possible to be in this particular domain; i.e. it checks as few values as possible and it fails early as possible if the number isn't a prime.

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))

UPDATE (2019/09/18): I stand corrected about my solution being "is as efficient as it is possible to be in this particular domain". The solution provided by @kanbagoly is actually more efficient in that it has fewer checks. His is implemented using Int. Here's his solution reimplemented using Long just in case you want to only do a copy/paste and not run into stupid Int versus Long issues:

def isPrime(long: Long): Boolean =
  if (long < 4L)
    long > 1L
  else if (((long % 2L) == 0L) || ((long % 3L) == 0L))
    false
  else
    (5L to math.sqrt(long).toLong by 6L)
      .forall(n => ((long % n) != 0L) && ((long % (n + 2L)) != 0L))
chaotic3quilibrium
  • 5,661
  • 8
  • 53
  • 86
  • 1
    I read somewhere that `(long & 1) == 0` might have an efficiency edge. – jwvh Jul 14 '19 at 02:35
  • That technique used to be needed, back in the early days of the JVM (prior to 2005). However, both the Java compiler and the HotSpot compiler now have explicit transforms/mappings for all of the basic bit operations, very much like the one you are describing (and many more). – chaotic3quilibrium Jul 14 '19 at 05:59
2

This can be a solutions.

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

Now coming back to the code that you have written, your code returns AnyVal and desired return type should be Boolean. And the reason behind that is in Scala (or any functional language) for loop is an expression not a control structure.

arpanchaudhury
  • 237
  • 3
  • 14
2

Comment on the former answers (except @jwvh): there is no need to use even numbers more than once. After a test by 2, the domain 3 to math.sqrt(integer).toInt by 2 must be used.

I have developed an accelerated tail-recursive version. It skips even values, and test two values in one go.

See it for yourself, running in your browser Scastie (remote JVM).

import java.lang.System.currentTimeMillis

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

// Primality by trial division

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

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

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

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

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

    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))
    assert(isPrime(i.toLong) == oeisPrimes.contains(i), s"Wrong $i")

  println(s"✔ Successfully completed without errors. [total ${currentTimeMillis - executionStart} ms]")

}

To be sure, this code test against the known list of primes for primes ánd composite numbers.

Epicurist
  • 903
  • 11
  • 17
1
def isPrime(n: Int) = (2 until n) forall(x => n % x !=0)
Das_Geek
  • 2,775
  • 7
  • 20
  • 26
  • 4
    Welcome to StackOverflow! Please edit your post to include an explanation for your code. This will make your answer more useful and more likely to be upvoted – Das_Geek Oct 16 '19 at 18:01
1

also you can use this recursive function:

def isPrime(n: Int):Boolean = {
  def isPrimeUntil(t: Int): Boolean =
    if (t<=1) true
    else n%t != 0 && isPrimeUntil(t-1)

    isPrimeUntil(n/2)
}
Arash Ahmadi
  • 101
  • 2
  • 5
0

That works fine for negative numbers and big numbers too. Prime numbers start from 2, 3, 5, ...

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

Also

@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)
   }
}
0

You can also use Wilson's theorem. p is prime if (p-1)! = -1 mod p. Normally computing (p-1)! is expensive as the number becomes huge, but computing the factorial mod p is less than p.

def prime(p):Boolean = {
  if (p==1)
    false
  else if (Seq(2,3,5,7,11).contains(p))
    false
  else
    // detect whether (p-1)! == -1 mod p
    (2 until p).fold(1)((acc:Int,i:Int) => (acc * i) % p) == p-1
}
Jim Newton
  • 594
  • 3
  • 16
-2

def primeNumber(range: Int): Unit ={

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)

}

Navin Gelot
  • 1,264
  • 3
  • 13
  • 32
  • 1
    This does not answer the question directly and displays very poor Scala style. Have you read any of the other answers already posted (over a year ago)? – jwvh Apr 03 '18 at 07:17
  • actually i just started leaning Scala from today and this is the first program that i written so i thought that it might help for beginner. thanks for reply – Navin Gelot Apr 03 '18 at 07:20
  • 1
    When a question is this old, and has many other answers, you should explain why you are posting a new and different answer. In this case your `isPrime` calculation is not significantly different from other posted answers and the rest of your code sets a bad example for beginners. – jwvh Apr 03 '18 at 07:29