I'm working on an exercise which requires me to implement isPrime in scala using tail recursion. I do have an implementation however, I'm having issues with producing the right base case.
So my algorithm involves checking all numbers from 2 to N/2, since N/2 would be the largest factor of N.
def isPrime(n: Int): Boolean = {
def isPrimeUntil(t: Int): Boolean = {
if(t == 2) true
else n % t != 0 && isPrimeUntil(t - 1)
}
isPrimeUntil(n/2)
}
So basically if I want to check if 15 is a prime I will check all numbers from 7 to 2.
Here is my trace:
isPrimeUntil(7) -> true && isPrimeUntil(6)
-> true && isPrimeUntil(5)
-> false && isPrimeUntil(4)
Because of short-circuit evaluation, the function returns false at this point.
However, my implementation fails for the basic case of checking if 3 is prime.
3 isn't your only problem. It also returns true
for 4
... Your base case should be 1
, not 2
:
def isPrimeUntil(t: Int): Boolean = t == 1 || t > 1 && n%t != 0 && isPrimeUntil(t-1)
Although Krzystof correctly pointed that the source of the problem is integer division, I don't like his solution. I believe that the proper fix is change the test to
if(t <= 2) true
With such check in the case of n = 3
and so n/2 = 1
it will stop without going to t = 0
.
Some benefits:
(t <= 2)
on almost any modern hardware is as efficient as the check for (t == 2)
(n.toDouble/2).ceil.toInt
that way. It's easier and faster to write (n+1)/2
instead of doing 2 conversion (to double and back to int) n
( (n+1)/2
is never the smallest divisor for an odd n
where there is a difference between n/2
and ceil(n/2)
)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.