defprime?(n) raiseTypeErrorunless n.kind_of?(Integer) 2.upto(Integer.sqrt(n)) {|x| returnfalseif n % x == 0 } returntrue end
这里可以稍作改进,可以在自增时自动跳过偶数部分,这可以通过每次自增2实现:
1 2 3 4 5 6 7 8 9
defprime?(n) raiseTypeErrorunless n.kind_of?(Integer) returntrueif n == 2 returnfalseif n % 2 == 0 3.step(Integer.sqrt(n), 2) {|x| returnfalseif n % x == 0 } returntrue end
给定一个数求出所有小于它的素数
例如给定一个数20,返回所有小于它的素数,即[2, 3, 5, 7, 11, 13, 17]。
1 2 3 4 5 6 7
defprimes(n) arr = [] 2.upto(n) do |x| arr << x if prime?(x) end arr end
# 每次跳过2 defprime2?(n) raiseTypeErrorunless n.kind_of?(Integer) returntrueif n == 2 3.step(Integer.sqrt(n), 2) {|x| returnfalseif n % x == 0 } returntrue end
# 每次跳过6 defprime6?(n) raiseTypeErrorunless n.is_a? Integer returntrueif n == 2or n == 3 returnfalseif n % 6 != 1or n % 6 != 5 5.step(Integer.sqrt(n), 6) do |x| returnfalseif n % x == 0or n % (x+2) == 0 end true end
# 每次跳过30 defprime30?(n) raiseTypeErrorunless n.is_a? Integer returntrueif n == 2or n == 3or n == 5 case n % 30 when1, 7, 11, 13, 17, 19, 23, 29 7.step(Integer.sqrt(n), 30) do |x| returnfalseif n % x == 0or n % (x + 4) == 0or n % (x + 6) == 0or n % (x + 10) == 0or n % (x + 12) == 0or n % (x + 16) == 0or n % (x + 22) == 0or n % (x + 24) == 0 end returntrue else false end end
Benchmark.bm(15) do |bm| bm.report("official") do 2.upto(n) do |x| prime_official_arr << x ifPrime.prime?(x) end end bm.report("2n") do 2.upto(n) do |x| prime2_arr << x if prime2?(x) end end bm.report("6n") do 2.upto(n) do |x| prime6_arr << x if prime6?(x) end end bm.report("30n") do 2.upto(n) do |x| prime30_arr << x if prime30?(x) end end end
p prime_official_arr == prime2_arr p prime_official_arr == prime6_arr p prime_official_arr == prime30_arr
测试结果:
1 2 3 4 5 6 7 8
user system total real official 24.656250 0.000000 24.656250 ( 24.711801) 2n 10.515625 0.000000 10.515625 ( 10.526535) 6n 5.562500 0.000000 5.562500 ( 5.578110) 30n 3.703125 0.015625 3.718750 ( 3.713207) true true true