2010-08-29 25 views
13

Estoy repasando los problemas en Project Euler para enseñarme la programación de Ruby. Sé que hay una función incorporada para hacer esto, pero estoy evitando las funciones integradas para ayudarme a aprender.Ruby: determine si un número es un número primo

Así que tengo que escribir un método para determinar si un número es primo. El primer método funciona, pero el segundo no. ¿Alguien puede explicar por qué?

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

Esto no es una respuesta a su pregunta ... pero por qué te la comprobación de todos los números después de que haya encontrado que no es un número primo? Ya * * obtuvo una respuesta definitiva a su pregunta. –

+0

Sí, me di cuenta de eso, pero lo hice de esa manera para asegurarme de que sé cómo funcionan los operadores booleanos en Ruby. –

+0

Se puede desarrollar un algoritmo más eficiente con el siguiente enfoque: no itere sobre números pares (no solo omítelos) y corte el bucle al 5-10% del tamaño original. Los detalles están aquí: http://stackoverflow.com/questions/26792960/why-doesnt-my-ruby-coding-for-finding-prime-numbers-work/32806718#32806718 – Anatoly

Respuesta

17

Es porque = es de mayor precedencia que or. Ver Ruby's operator precedence table a continuación (mayor a menor prioridad):

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

La línea problemática está siendo analizado como ...

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

... que por cierto no es lo que quiere decir. Hay dos soluciones posibles:

Fuerza la precedencia a ser lo que realmente significa ...

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

... o utilizar el operador || lugar, que tiene mayor precedencia que =:

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

Es por eso que me encanta StackOverflow. Gracias a un millón –

+1

escribiendo foundDivider || = ((n% d) == 0) será más agradable. –

+1

Agradable. ¡Encontré la pregunta, y la respuesta útil! Yo también estoy corriendo por Project Euler para aprender Ruby. Una sugerencia de mejora del rendimiento que tengo es cambiar el rango de ** 2 .. (n-1) ** a ** 2 .. (Math.sqrt (n)) **; reduce el número de iteraciones significativamente. –

5

Ruby viene con clases predefinidas como Prime. Todo lo que tienes que hacer es solicitar esa clase en tu proyecto.

require 'prime' 

que, usted puede utilizar algunos de los métodos Prime como primera obtener primero x elementos principales:

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

O usted podría hacer algo como esto:

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

Espero que esto te sea útil.

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

Un número primo es un número que no tiene divisores positivos distintos de uno mismo y 1.

+0

sintaxis no funciona –

1

FYI - re: DarkMouses principal método anterior - Me pareció muy útil, pero hay algunos errores (creo) que falta explicar:

Cabe paréntesis en lugar de corchetes ... de lo contrario se obtiene una TypeError

Range can't be coerced into Fixnum (TypeError) 

en segundo lugar, que los primeros dos puntos antes 'falso' también causaría un error. Es una sintaxis incorrecta, hasta donde yo sé. Desaste de eso.

Por último, creo que lo hiciste a la inversa? Si corrige los errores que mencioné, devuelve verdadero si NO ES un primo y falso si lo es.

puedes colocar el operador ternario en conjunto, creo, y acaba de hacer:

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

Obviamente no cubre los casos extremos (0,1,2), sino de dejar que los pelos no divididas.

... Para aquellos que disfrutan hairsplitting, aquí está mi solución completa a este problema:

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

esperanza que no se pierda nada :)

+3

Es n en lugar de longitud en su código – PerseP

4

Encuentra los números primos de bucle:

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 

y utilizarlo como a continuación:

puts get_prime_no_upto(100) 

¡Salud!

3

Aquí es código que le pedirá que introduzca un número de registro de entrada privilegiada:

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

Sobre la base de la respuesta por Darmouse pero incluyendo casos extremos

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 gama de factores debería comenzar en 2 y terminar en la raíz cuadrada de n porque cada número es divisible por uno y ningún número es divisible por dos números mayores que su raíz cuadrada.

Explicación: Un número no primo es el producto de dos números.

n = f1 * f2 

n es siempre divisible por su raíz cuadrada por lo tanto f1f2 y no puede ser mayor que la raíz cuadrada de n, de lo contrario f1 * f2 sería mayor que n. Por lo tanto, al menos un factor es menor o como máximo igual a Math.sqrt(n). En el caso de encontrar números primos, solo es necesario encontrar un factor, por lo que deberíamos pasar del 2 a la raíz cuadrada de n.

0

Esto es un poco fuera del tema de acuerdo a los detalles, pero correcto para el título: mediante la integración de fiesta en Ruby que podría hacer:

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

fiesta factor función devuelve un número más todos sus factores, entonces, si el número es primo, habrá dos palabras contadas.

Esto es útil para código de golf solamente.

0

yo probamos este y funcionó:

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 
Cuestiones relacionadas