web-dev-qa-db-fra.com

Comment générer les n premiers nombres premiers?

J'apprends Ruby et je fais des trucs en mathématiques. Une des choses que je veux faire est de générer des nombres premiers.

Je veux générer les dix premiers nombres premiers et les dix premiers seulement. Je n'ai aucun problème à tester un nombre pour voir s'il s'agit d'un nombre premier ou non, mais je me demandais quel était le meilleur moyen de générer ces chiffres?

J'utilise la méthode suivante pour déterminer si le nombre est premier:

class Integer < Numeric
  def is_prime?
    return false if self <= 1
    2.upto(Math.sqrt(self).to_i) do |x|
      return false if self%x == 0
    end
    true
  end
end
24
Tony Petley

Dans Ruby 1.9, il existe une classe principale que vous pouvez utiliser pour générer des nombres premiers ou pour vérifier si un nombre est premier:

require 'prime'

Prime.take(10) #=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Prime.take_while {|p| p < 10 } #=> [2, 3, 5, 7]
Prime.prime?(19) #=> true

Prime implémente la méthode each et inclut le module Enumerable, afin que vous puissiez faire toutes sortes de choses amusantes comme le filtrage, le mappage, etc.

45
Scott Olson
require 'prime'

Prime.first(10) # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
10
Jörg W Mittag

Si vous souhaitez le faire vous-même, quelque chose comme ceci pourrait fonctionner:

class Integer < Numeric
    def is_prime?
        return false if self <= 1
        2.upto(Math.sqrt(self).to_i) do |x|
            return false if self%x == 0
        end 
        true
    end 

    def next_prime
        n = self+1
        n = n + 1 until n.is_prime?
        n   
    end 
end

Maintenant, pour obtenir les 10 premiers nombres premiers:

e = Enumerator.new do |y|
    n = 2
    loop do
        y << n
        n = n.next_prime
    end
end

primes = e.take 10
10
z5h

Les gens ont déjà mentionné la classe Prime, qui serait certainement la voie à suivre. Quelqu'un vous a également montré comment utiliser un Enumerator et je voulais contribuer une version utilisant un Fibre (il utilise votre méthode Integer#is_prime?):

primes = Fiber.new do
  Fiber.yield 2
  value = 3
  loop do
    Fiber.yield value if value.is_prime?
    value += 2
  end
end

10.times { p primes.resume }
7
Michael Kohl

Découvrez le tamis d'Eratosthène. Ce n'est pas spécifique à Ruby mais c'est un algorithme pour générer des nombres premiers. L’idée derrière cet algorithme est que vous avez une liste/un tableau de nombres

2..1000

Vous prenez le premier numéro, 2. Parcourez la liste et éliminez tout ce qui est divisible par 2. Vous resterez avec tout ce qui n'est pas divisible par 2 sauf 2 lui-même (par exemple, [2,3,5,7,9, 11 ... 999]

Allez au nombre suivant, 3. Et encore une fois, éliminez tout ce que vous pouvez diviser par 3. Continuez jusqu'à ce que vous atteigniez le dernier nombre et que vous obteniez un tableau de nombres premiers. J'espère que cela pourra aider.

http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

7
denniss
# First 10 Prime Numbers

number = 2
count = 1
while count < 10
  j = 2
  while j <= number
    break if number%j == 0
    j += 1
  end
  if j == number
    puts number 
    count += 1
  end
  number += 1
end
3
Jyothu

Je l'ai fait pour un kata de codage et j'ai utilisé le tamis d'Eratosthène.

puts "Up to which number should I look for prime numbers?"
number = $stdin.gets.chomp
n = number.to_i
array = (1..n).to_a

  i = 0

while array[i]**2 < n

i = i + 1
array = array.select do |element|
  element % array[i] != 0 || element / array[i] == 1


end
end

 puts array.drop(1)
1
Max Durden
class Numeric
  def prime?
    return self == 2 if self % 2 == 0

    (3..Math.sqrt(self)).step(2) do |x|
      return false if self % x == 0
    end

    true
  end
end

Avec cela, maintenant, 3.prime? renvoie true, et 6.prime? renvoie false

Sans passer aux efforts d'implémentation de l'algorithme tamis, il est possible de gagner du temps en vérifiant simplement la divisibilité jusqu'à la racine carrée et en sautant les nombres impairs. Ensuite, parcourez les nombres, en vérifiant leur primauté.

Rappelez-vous: temps humain> temps machine.

1
Rishi

Je pense que cela peut être une solution coûteuse pour un très grand nombre max mais semble bien fonctionner sinon

def multiples array
  target = array.shift 
  array.map{|item| item if target % item == 0}.compact
end

def prime? number
  reversed_range_array = *(2..number).reverse_each
  multiples_of_number = multiples(reversed_range_array)
  multiples_of_number.size == 0 ? true : false
end

def primes_in_range max_number
  range_array = *(2..max_number)
  range_array.map{|number| number if prime?(number)}.compact
end
1
Shay Narang

Voici un moyen de générer les nombres premiers jusqu’à un argument "max" à partir de zéro, sans utiliser Prime ni Math. Laissez-moi savoir ce que vous pensez.

def prime_test max
    primes = []
    (1..max).each {|num| 
        if
            (2..num-1).all? {|denom| num%denom >0}
        then
            primes.Push(num)
        end
    }
    puts primes
end

prime_test #enter max
1
Sam S

Mise en œuvre du tamis d'Eratosthene (plus ou moins)

def primes(size)
    arr=(0..size).to_a
    arr[0]=nil
    arr[1]=nil
    max=size
    (size/2+1).times do |n|
        if(arr[n]!=nil) then
            cnt=2*n
            while cnt <= max do
                arr[cnt]=nil
                cnt+=n
            end
        end
    end
    arr.compact!
end

De plus voici un one-liner que j'aime beaucoup

def primes_c a
    p=[];(2..a).each{|n| p.any?{|l|n%l==0}?nil:p.Push(n)};p
end

Bien sûr, ceux-ci trouveront les nombres premiers dans les premiers nombres n et non les premiers nombres premiers n, mais je pense qu'une adaptation ne demandera pas beaucoup d'effort.

1
Gabber

Pas du tout lié à la question elle-même, mais à titre d'information:

  • si quelqu'un ne veut pas continuer à générer des nombres premiers encore et encore (économiseur de ressources glouton)
  • ou peut-être vous savez déjà que vous devez travailler avec des nombres premiers ultérieurs d'une manière quelconque
  • autres cas inconnus et merveilleux

Essayez avec cet extrait:

  require 'prime'

  for p in Prime::Generator23.new
    # `p` brings subsequent prime numbers until the end of the days (or until your computer explodes)
    # so here put your fabulous code
    break if #.. I don't know, I suppose in some moment it should stop the loop
  end
  fp

Si vous en avez besoin, vous pouvez également utiliser un autre générateur plus complexe, tel que Prime::TrialDivisionGenerator ou Prime::EratosthenesGenerator. Plus d'informations

0
Alter Lagos

Ruby: Imprime N nombres premiers http://mishra-vishal.blogspot.in/2013/07/include-math-def-printnprimenumbernoofp.html

include Math

def print_n_prime_number(no_of_primes=nil)

  no_of_primes = 100 if no_of_primes.nil?

  puts "1 \n2"

  count = 1

  number = 3

  while count < no_of_primes

sq_rt_of_num = Math.sqrt(number)

number_divisible_by = 2

while number_divisible_by <= sq_rt_of_num

  break if(number % number_divisible_by == 0)

  number_divisible_by = number_divisible_by + 1

end

if number_divisible_by > sq_rt_of_num

  puts number

  count = count+1

end

number = number + 2

  end

end

print_n_prime_number
0
user2206324