2010-09-15 27 views
5

Actualmente estoy tratando de entender Python y he llegado a un punto muerto en las funciones recursivas. En Think Python, uno de los ejercicios es escribir una función que determina si el número un es una potencia del número b usando la siguiente definición:¿Por qué mi función recursiva devuelve None?

"Un número, una, es una potencia de b si es divisible por by a/b es una potencia de b. Escribe una función llamada is_power que toma los parámetros a y b y devuelve True si a es una potencia de b ".

El estado actual de mi función es:

def isPower(a,b): 
    return a % b == 0 and (a/b) % b == 0 

print isPower(num1,num2) 

Tal como es, esto produce el resultado que esperaba. Sin embargo, el capítulo se centra en escribir funciones recursivas para reducir la redundancia y no estoy muy seguro de cómo puedo convertir el final "(a/b)% b == 0" en una recursión. Lo intenté:

def isPower(a,b): 
    if a % b != 0: 
     return False 
    elif isPower((a/b),b): 
     return True 

Pero eso simplemente devuelve None.

¿Cuál es la forma correcta de recurrir esta función?

+3

Se debe tener cuidado de que el significado del operador '/' ha cambiado en Python 3+, desde devolver un número entero hasta devolver un flotador, para que tu código se rompa. Cambie a '//' en su lugar, que siempre devolverá un int. –

+2

tenga en cuenta que su primer intento no verifica si a es una potencia de b, sino que si a es un múltiplo de b^2. prueba isPower (12,2), devolvería True. – Javier

+0

Solo así se dice, su primera versión de isPower está rota: solo mostrará si 'a' es un múltiplo de' b^2'. Volverá a ser cierto para 'isPower (2, 1)', por ejemplo, que nunca debería ser cierto. Para el caso, es posible que desee asegurarse de que cualquier versión recursiva compruebe si '(b == 1 && a! = 1)' antes de continuar, o se quedará atascado en un bucle infinito o devolverá algo incorrecto. – cHao

Respuesta

3

Se están olvidando un caso base, cuando un == 1:

def isPower(a,b): 
    if a == 1: 
     return True 
    if a % b != 0: 
     return False 
    elif isPower((a/b),b): 
     return True 
    else 
     return False 

Sin embargo, esto tiene alguna otros problemas: si a es 0, nunca terminará y si b es 0, obtendrás una división por cero.

Aquí es una solución detallado que por lo que yo puedo decir funcione para todas las combinaciones de números enteros:

def isPower(a,b): 
    if a == 0 or b == 0: 
     return False 
    def realIsPower(a, b): 
     if a == 1: 
      return True 
     elif a%b != 0: 
      return False 
     elif realIsPower((a/b), b): 
      return True 
     else: 
      return False 
    return realIsPower(a, b) 

EDIT: Mi código no funcionó para los casos en que tanto a como b son negativos. Ahora estoy comparando sus valores absolutos.

EDIT2: Silly me, x^0 == 1, entonces a == 1 SIEMPRE debe volverse verdadero. Eso también significa que no tengo que comparar a a antes de la recursión. Gracias @Javier.

+0

Gracias. Esto aclaró exactamente lo que me faltaba. Después de retocar un poco más con eso antes, había alcanzado un ciclo máximo de recursión, pero no pude encontrar la forma de detenerlo. Supongo que asumí que el intérprete sabría que solo quería que se detuviera una vez más. Ahora entiendo que, al escribir una llamada recursiva, una de las pruebas para permitir que se llegue a esa rama ELIF debe ser capaz de detenerla. Esta fue solo una función de práctica, por lo que permitir una base de 1 hubiera estado bien, ¡pero gracias por hacer todo lo posible para ayudar! – bobby

+1

¡Oye, me alegro de poder ayudarte! Recuerde siempre que hay dos cosas requeridas para todas las funciones recursivas: un caso (s) base y una llamada recursiva. A veces (como en este caso) hay más de un caso base. –

2

necesita un caso adicional, ya que cuando ambos condicionales devuelven false

def isPower(a,b): 
    if a % b != 0: 
     return False 
    elif isPower((a/b),b): 
     return True 
    else 
     return False 
+0

Creo que se refería a% b, no a & b – Bob

+0

Esto siempre será falso. –

+0

También debe tener en cuenta el caso base. Acabo de editar el error tipográfico. –

1
def isPower (a,b): 
    return a==1 or (a!=0 and b!=0 and b!=1 and isPower((a/b),b)) 
+0

Esto siempre volverá a ser cierto en el caso de que a sea inicialmente 1, sin embargo, ese es solo el caso si b es 1 o -1. –

+0

Gracias por su ayuda, Javier. Tus respuestas y las de Niki combinadas eran exactamente lo que necesitaba para que todo se repitiera en mi cabeza. Entiendo la importancia de andamiar y escribir código excesivamente detallado con muchas pruebas en el camino, pero una vez que me siento cómodo con la sintaxis y la lógica, me gustaría poder producir el código más corto posible que produzca el mismo efecto. Esta respuesta fue genial para ver cómo se ve la respuesta de Niki como una línea para referencia futura. Lástima que no puedo tener dos respuestas aceptadas! – bobby

+0

@Niki Yoshiuchi: 1 es un poder de cualquier número (x^0 = 1 para cualquier x) – Javier

0

probar esto,

def ispower(a,b): 
    if b==a: 
    return True 
    elif a<b: 
    return False 
    else: 
    return ispower(a*1.0/b, b) 
+0

una explicación ayudaría a esta respuesta – dove

1

Aquí está mi código. Por lo que he probado, funciona:

def ispower(a, b): 

    if b == 1 or b == 0: 
     return False 
    if b <= 0 or a <= 0: 
     return False 
    if a % b == 0: 
     if ((a/b)/b) == 1: 
      return True 
     else: 
      return ispower(a/b, b) 
    else: 
     return False 
     print ispower(-10, 2) 
0
def is_power (a, b): 

    if a == 1: 
     return True 
    if a == 0 and b == 0: 
     return True 
    if a == 0 or b == 0: 
     return False 
    if a%b != 0: 
     return False 
    elif is_power ((a/b), b): 
     return True 
0

Aquí es mi respuesta, que es un poco más limpia:

def is_power(a, b): 
    if a == 1: 
     return True 
    if a == 0 or b == 0: 
     return False 
    if a % b == 0 and is_power(a/b, b): 
     return True 
    else: 
     return False 
Cuestiones relacionadas