Ruby - determine if a number is a prime
It's because =
is of higher precedence than or
. See Ruby's operator precedence table below (highest to lowest precedence):
[ ] [ ]=
**
! ~ + -
* / %
+ -
>> <<
&
^ |
<= < > >=
<=> == === != =~ !~
&&
||
.. ...
? :
= %= { /= -= += |= &= >>= <<= *= &&= ||= **=
defined?
not
or and
if unless while until
begin/end
The problematic line is being parsed as...
(foundDivider = ((n % d) == 0)) or foundDivider
...which is certainly not what you mean. There are two possible solutions:
Force the precedence to be what you really mean...
foundDivider = (((n % d) == 0) or foundDivider)
...or use the ||
operator instead, which has higher precedence than =
:
foundDivider = ((n % d) == 0) || foundDivider
Ruby Prime number program
Let's calculate the square root of 7 (a prime number) and 8 (a composite number):
Math.sqrt(7) #=> 2.6457513110645907
Math.sqrt(8) #=> 2.8284271247461903
This doesn't really help, does it? Apparently, you can't determine if a number is a prime number by calculating its square root.
Instead, you have to check the number's divisors. From Wikipedia:
A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
Let's determine the divisors of 7: (using the modulo operator %
)
7 % 1 #=> 0 <- 7 is divisible by 1
7 % 2 #=> 1
7 % 3 #=> 1
7 % 4 #=> 3
7 % 5 #=> 2
7 % 6 #=> 1
7 % 7 #=> 0 <- 7 is divisible by 7
This satisfies the above definition - 7 is a prime number.
Now, let's determine the divisors of 8:
8 % 1 #=> 0 <- 8 is divisible by 1
8 % 2 #=> 0 <- 8 is divisible by 2
8 % 3 #=> 2
8 % 4 #=> 0 <- 8 is divisible by 4
8 % 5 #=> 3
8 % 6 #=> 2
8 % 7 #=> 1
8 % 8 #=> 0 <- 8 is divisible by 8
8 has two additional divisors 2 and 4. Therefore, 8 is not a prime number.
In Ruby, you could use select
to find the divisors:
(1..7).select { |d| 7 % d == 0 } #=> [1, 7]
(1..8).select { |d| 8 % d == 0 } #=> [1, 2, 4, 8]
Finally, here's a variant of your Ruby code that checks if a given number num
has exactly two divisors, 1
and num
itself:
prime_array = []
(1...100).each do |num|
if (1..num).select { |d| num % d == 0 } == [1, num]
prime_array.push(num)
end
end
prime_array
#=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
The above code can be optimized. I leave that to you.
Checking for prime number in ruby
The proximate issue you are facing is, this is not valid Ruby: (counter == Math.sqrt(num).ceil) ? "false"
?
, as an operator, is a part of the trinary operator ... ? ... : ...
, and always comes in pair with a :
, as you write in your next line. Then again, overuse of trinary operator is also not good. You also have a problem with control flow: after evaluating "true"
, the loop will continue, counter
won't change, and you got an infinite loop.
I suggest you work out what the algorithm should be. Write it in English, if necessary. Then make sure you convert it to Ruby correctly.
Also, Ruby methods should be in snake case (lowercase with underscores between words), so PrimeTime
is not a good name. I suggest prime?
(as question marks are also allowed in identifiers) if you will be returning a boolean value (true
or false
). If you are returning a string (as you seem to be trying to do), try check_for_primality
or something similar (without the question mark).
Also... if remainder is zero, the number is not prime. I think you have your tests switched around.
If you are still stumped:
def prime?(num); (2..Math.sqrt(num)).each do |counter|; if (num % counter == 0); return false end end; true; end
EDIT On rewritten code: break & return false
doesn't do what you want. They are both control statements; if you break
, return
won't happen. Even if it did, if the break wasn't there, it would have been better to write and
, or at least &&
, not &
(binary and).
Your logic is still wrong though: PrimeTime(16)
is true
, for example, is not really what I'd expect from a primality testing function.
Ruby - method for generating prime numbers
Got a good idea for your implementation:
@primes = []
def prime_numbers(n)
i = 2
while @primes.size < n do
@primes << i if is_prime?(i)
i += 1
end
@primes
end
def is_prime?(n)
@primes.each { |prime| return false if n % prime == 0 }
true
end
This is based on the idea that non-prime numbers have prime factors :)
Why doesnt my ruby coding for finding prime numbers work?
You have a few problems. One was identified earlier: the location of the statement i = 2
. Here is your code with that fixed.
def is_prime?(*nums)
nums.each do |num|
i = 2
while i < num
if num % i == 0
puts "#{num} is not a prime"
else
puts "#{num} is a prime"
end
i += 1
end
end
end
When num % i == 0
you've determined the number is not prime, and print a message to that effect, but then you continue checking to see if it is divisible all larger numbers less than num
. Each time num % i == 0
you print out that it's not prime. The point is that you don't need to keep checking once you determine a number is not prime.
Another problem is whenever num % i != 0
you print that the number is prime. That's premature, however. You can't draw that conclusion until you determine that num % i != 0
for all integers less than num
.
Let's see how to fix these problems. I think the easiest ways is to write a separate method that determines if a single number is prime. I've called that method is_prime?
and renamed the main method is_each_prime?
.
def is_each_prime?(*nums)
nums.each { |num|
puts "#{num} is #{ is_prime?(num) ? '' : "not " }a prime" }
end
def is_prime?(num)
(2...Math.sqrt(num)).all? { |i| num % i != 0 }
end
puts is_each_prime?(21, 23, 17)
#=> 21 is not a prime
# 23 is a prime
# 17 is a prime
One advantage of creating a separate method is_prime?
is that you can test it separately, to make sure it is working properly.
Related Topics
Difference Between Plugins and Ruby Gems
How to Include Video in Jekyll Markdown Blog
Fastest Way to Check If a String Matches a Regexp in Ruby
Rspec: How to Stub an Instance Method Called by Constructor
I Have a Gem Installed But Require 'Gemname' Does Not Work. Why
How to Install Nokogiri Ruby Gem with Mkmf.Log Saying Libiconv Not Found
Difference Between '%{}', '%Q{}', '%Q{}' in Ruby String Delimiters
How to Deal with Not Knowing What Exceptions Can Be Raised by a Library Method in Ruby
Hashes of Hashes Idiom in Ruby
How to Get Elapsed Time in Milliseconds in Ruby
How to Get the Line of Code That Triggers a Query
What Does "Wrong Number of Arguments (1 for 0)" Mean in Ruby
How to Catch Errno::Econnreset Class in "Case When"
Rails - Multiple Top Level Domains and a Single Session/Cookie
Suppressing the Output of a Command Run Using 'System' Method While Running It in a Ruby Script