(To answer the question first: yes, you are doing something wrong. As BLUEPIXY mentions, you need to place require 'prime' somewhere above the line that calls Prime.prime? Usually on line 1.)
Now many answers have been given that do not use Prime.prime? , and I thought it would be interesting to compare some of them, along with my own possible improvement, which I had in mind.
TL DR
I tested several solutions, including a couple of my own; itโs best to use a while and skip even numbers.
Methods Verified
Here are the methods I used from the answers:
require 'prime' def prime1?(num) return if num <= 1 (2..Math.sqrt(num)).none? { |i| (num % i).zero? } end def prime2?(num) return false if num <= 1 Math.sqrt(num).to_i.downto(2) {|i| return false if num % i == 0} true end def prime3?(num) Prime.prime?(num) end def prime4?(num) ('1' * num) !~ /^1?$|^(11+?)\1+$/ end
prime1? - An updated version of AndreiMotinga. prime2? - its original version (without the extra method each ). prime3? is a reboot using the prime library. prime4? - Saurabh regex version (except Fixnum monkey patch).
A couple more methods to check
The improvement I had in mind was to take advantage of the fact that even numbers cannot be prime and to exclude them from the iteration loop. Thus, this method uses the #step method to iterate over only odd numbers, starting at 3:
def prime5?(num) return true if num == 2 return false if num <= 1 || num.even? 3.step(Math.sqrt(num).floor, 2) { |i| return false if (num % i).zero? } true end
I also thought it would be interesting to see how a โprimitiveโ implementation of the same algorithm could be performed using a while . So here is one:
def prime6?(num) return true if num == 2 return false if num <= 1 || num.even? i = 3 top = Math.sqrt(num).floor loop do return false if (num % i).zero? i += 2 break if i >= top end true end
Benchmarks
I did a simple test for each of them, calculating the call time of each method with a prime number of 67,280,421,310,721. For instance:
start = Time.now prime1? 67280421310721 puts "prime1? #{Time.now - start}" start = Time.now prime2? 67280421310721 puts "prime2? #{Time.now - start}"
As I suspected, I would have to do this, I canceled prime4? after about 60 seconds. Presumably, it takes more than 60 seconds to assign a memory of 6.7 trillion '1' to the north, and then apply a regular expression filter to the result, assuming that you can allocate the required amount of memory on this computer. (In my opinion, this is not so: I went into irb , inserted '1' * 67280421310721 , cooked and ate lunch, went back to the computer and found Killed: 9 as an answer. It looks like SignalException raised when the process was killed.)
Other results:
prime1? 3.085434
prime2? 1.149405
prime3? 1.236517
prime5? 0.748564
prime6? 0.377235
Some (preliminary) conclusions
I believe that it is not surprising that a primitive solution with a while loop is the fastest, since it is probably closer than others to what happens under the hood. Although itโs a little surprising that it is three times faster than Prime.prime? . (After looking at the source code in the document, it became less noticeable. There are a lot of bells and whistles in the Prime object.)
The updated version of AndreiMotinga is almost three times slower than its original, which suggests that the #none? method #none? not very effective, at least in this context.
Finally, the regex version may be cool, but it doesn't seem to have much practical value, and using it in a base class monkey patch looks like something that should be completely avoided.