Prime number function in R

dsmoore picture dsmoore · Nov 4, 2013 · Viewed 45.2k times · Source

I am trying to create a function to test if a given integer is a prime number, I tried using the following:

tpn <- function(prime.num){

    if(prime.num==2){
        print("PRIME")
    } else {

    if(prime.num%%(2:(prime.num-1))!=0){
        print("PRIME")

    } else { 
        print("NOT PRIME")

}}}

This doesn't work, although I cant understand why. I am checking to see if the given number can be divided by any of the integers up to this number with no remainders. If it cant, then the number is prime.

Another solution I found was:

tpn <- function(pn){

    if(sum(pn/1:pn==pn%/%1:pn)==2)
            print("prime")

}

This works. Although, I cant get my head around what sum(pn/1:pn == pn%/%1:pn) == 2 is actually testing for.

Answer

flodel picture flodel · Nov 4, 2013

A number a is divisible by a number b if the result of the division a / b is equal to the result of the integer division a %/% b. Any integer pn can be divided by at least two numbers: 1 and pn. Prime numbers are those than can only be divided by those two. Breaking out the code:

  1. pn / 1:pn are the results of the divisions by 1, 2, ..., pn
  2. pn %/% 1:pn are the results of the integer divisions by 1, 2, ..., pn
  3. sum(pn / 1:pn == pn %/% 1:pn) are how many of these are equal, i.e., the number of integer divisors of pn. If this number is 2, you have a prime.

What was wrong with your code: if needs to test if something is TRUE or FALSE but you were passing it a whole vector. Also, your logic was wrong. It should have been:

is.prime <- function(num) {
   if (num == 2) {
      TRUE
   } else if (any(num %% 2:(num-1) == 0)) {
      FALSE
   } else { 
      TRUE
   }
}

And once you've settled on returning a logical, you can make your code a lot shorter:

is.prime <- function(n) n == 2L || all(n %% 2L:max(2,floor(sqrt(n))) != 0)

(which incorporates @Carl's comment about not checking all numbers.)