2010-08-29 6 views
13

Je traverse les problèmes sur Project Euler pour enseigner moi-même la programmation Ruby. Je sais qu'il existe une fonction intégrée pour ce faire, mais j'évite les fonctions intégrées pour m'aider à apprendre.Ruby - déterminer si un nombre est un premier

Je dois donc écrire une méthode pour déterminer si un nombre est un nombre premier. La première méthode fonctionne, mais la seconde ne fonctionne pas. Quelqu'un peut-il expliquer pourquoi?

def is_prime n 
    for d in 2..(n - 1) 
    if (n % d) == 0 
    return false 
    end 
    end 

    true 
end 

def is_prime2 n 
    foundDivider = false 
    for d in 2..(n - 1) 
    foundDivider = ((n % d) == 0) or foundDivider 
    end 
    not foundDivider 
end 
+0

Ce n'est pas une réponse à votre question ... mais pourquoi sont-vous vérifier tous ces chiffres une fois que vous avez trouvé ce n'est pas une prime? Vous avez * déjà * obtenu une réponse définitive à votre question. –

+0

Ouais je l'ai réalisé - mais je le faisais pour être sûr de savoir comment fonctionnent les opérateurs booléens dans Ruby –

+0

Un algorithme plus efficace peut être développé avec l'approche suivante: ne pas itérer sur des nombres pairs (pas seulement les ignorer) et couper la boucle à 5-10% de la taille d'origine. Les détails sont ici: http://stackoverflow.com/questions/26792960/why-doesnt-my-ruby-coding-for-finding-prime-numbers-work/32806718#32806718 – Anatoly

Répondre

17

C'est parce que = est de priorité plus élevé que or. Voir ci-dessous Ruby's operator precedence table (le plus à la priorité la plus basse):

[ ] [ ]= 
** 
! ~ + - 
* / % 
+ - 
>> << 
& 
^ | 
<= < > >= 
<=> == === != =~ !~ 
&& 
|| 
.. ... 
? : 
= %= { /= -= += |= &= >>= <<= *= &&= ||= **= 
defined? 
not 
or and 
if unless while until 
begin/end 

La ligne problématique est en cours d'analyse comme ...

(foundDivider = ((n % d) == 0)) or foundDivider 

... qui est certainement pas ce que vous voulez dire. Il existe deux solutions possibles:

Force de la priorité d'être ce que vous voulez vraiment dire ...

foundDivider = (((n % d) == 0) or foundDivider) 

... ou utiliser l'opérateur || au lieu, qui a une priorité supérieure =:

foundDivider = ((n % d) == 0) || foundDivider 
+4

C'est pourquoi j'aime StackOverflow. Merci un million –

+1

écriture foundDivider || = ((n% d) == 0) sera plus agréable. –

+1

Nice. J'ai trouvé la question, et la réponse utile! Moi aussi, je cours à travers Project Euler pour apprendre Ruby. Une suggestion d'amélioration des performances que j'ai est de changer la gamme de ** 2 .. (n-1) ** à ** 2 .. (Math.sqrt (n)) **; réduit le nombre d'itérations de manière significative. –

5

Ruby est livré avec des classes prédéfinies telles que Prime. Tout ce que vous avez à faire est d'exiger cette classe dans votre projet.

require 'prime' 

Than, vous pouvez utiliser certaines des méthodes Prime telles que premier pour obtenir d'abord x éléments principaux:

Prime.first(5) # Ret => [2, 3, 5, 6, 11] 

Ou vous pourriez faire quelque chose comme ceci:

Prime.each(100) do |prime| 
    p prime # Ret => [2, 3, 5, 7, 11, ..., 97] 
end 

J'espère que vous trouverez cela utile.

4
def prime(n) 
    (2..n/2).none?{|i| n % i == 0} 
end 

Un nombre premier est un nombre qui n'a pas diviseurs autres que lui-même et 1.

+0

la syntaxe ne fonctionne pas –

1

Pour votre information - re: DarkMouses principale méthode ci-dessus - je l'ai trouvé vraiment utile, mais il y a quelques erreurs (Je pense) qui doivent être expliquées:

Il devrait être entre parenthèses plutôt que des crochets ... Sinon, vous obtenez un TypeError

Range can't be coerced into Fixnum (TypeError) 

en second lieu, que le premier colon avant 'false' provoquerait aussi une erreur. C'est une syntaxe incorrecte, pour autant que je sache. Débarrassez-vous de cela.

Enfin, je pense que vous l'avez eu dans le mauvais sens? Si vous corrigez les erreurs que j'ai mentionnées, il retourne vrai si ce n'est pas un premier, et faux si c'est le cas.

Vous pouvez laisser tomber l'opérateur ternaire tout à fait, je pense, et il suffit de faire:

def prime?(n) 
    (2..n/2).none?{|i| n % i == 0} 
end 

Évidemment, il ne couvre pas les cas de bord (0,1,2), mais nous allons les cheveux fractionne pas.

... Pour ceux qui aiment l'ergotage, voici ma solution complète à ce problème:

def prime?(n) 
     return false if n < 2 
     (2..Math.sqrt(n)).none? {|num| length % num == 0} 
    end 

espère ne rien raté :)

+3

C'est n au lieu de la longueur dans votre code – PerseP

4

Trouver des nombres premiers de la boucle:

def get_prime_no_upto(number) 
    start = 2 
    primes = (start..number).to_a 
    (start..number).each do |no| 
    (start..no).each do |num| 
     if (no % num == 0) && num != no 
     primes.delete(no) 
     break 
     end 
    end 
    end 
    primes 
end 

et l'utiliser comme ci-dessous:

puts get_prime_no_upto(100) 

À la votre!

3

le code est ici qui vous demandera d'entrer un numéro pour le premier chèque:

puts "welcome to prime number check" 
puts "enter number for check: " 
    n = gets 
    n = n.to_i 

def prime(n) 
    puts "That's not an integer." unless n.is_a? Integer 
    is_prime = true 
    for i in 2..n-1 
    if n % i == 0 
     is_prime = false 
    end 
    end 
    if is_prime 
    puts "#{n} is prime!" 
    else 
    puts "#{n} is not prime." 
    end 
end 

prime(n) 
2

Sur la base de la réponse par Darmouse mais y compris les cas de pointe

def prime? (n) 
    if n <= 1 
     false 
    elsif n == 2 
     true 
    else 
     (2..n/2).none? { |i| n % i == 0} 
    end 
end 
3
def prime? n 
    (2..Math.sqrt(n)).none? {|f| n % f == 0} 
end 

La gamme de facteurs devrait commencer à 2 et se terminer à la racine carrée de n parce que chaque nombre est divisible par un et aucun nombre n'est divisible par deux nombres plus grands que sa racine carrée. Explication: Un nombre non premier est le produit de deux nombres.

Explication: Un nombre non premier est le produit de deux nombres.

n = f1 * f2 

n est toujours divisible par sa racine carrée afin que les deux f1 et f2 ne peut pas être supérieure à la racine carrée de n, sinon f1 * f2 serait supérieure à n. Par conséquent, au moins un facteur est inférieur ou au plus égal à Math.sqrt(n). Dans le cas de trouver des nombres premiers, il est seulement nécessaire de trouver un facteur, donc nous devrions boucler de 2 à la racine carrée de n.

0

Ceci est un peu hors sujet selon les détails, mais correct pour le titre: en utilisant l'intégration bash en Ruby, vous pouvez faire:

def is_prime n 
    `factor #{n}`.split.count < 3 
end 

bash factor fonction retourne un nombre ainsi que tous ses facteurs, donc si le nombre est premier, il y aura deux mots.

Ceci est utile pour code golf uniquement.

0

J'ai essayé et cela a fonctionné:

def prime?(n) 
    return false if n < 2 
    return true if n == 3 || n == 2 
    if (2...n-1).any?{|i| n % i == 0} 
     false 
    else 
     true 
    end 
end 
Questions connexes