2010-09-15 4 views
5

В настоящее время я пытаюсь обернуть голову изучением Python, и я пришел к тому, чтобы немного отдохнуть на рекурсивных функциях. В Think Python, одно из упражнений, чтобы написать функцию, которая определяет, является ли число является степенью числа б используя следующее определение:Почему моя рекурсивная функция возвращает None?

«число, а, является сила Ь, если он делится на b и a/b является степенью b. Напишите функцию, называемую is_power, которая принимает параметры a и b и возвращает True, если a является степенью b. "

Текущее состояние моей функции:

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

print isPower(num1,num2) 

Как это, это дает результат я ожидаю. Однако глава сосредоточена на написании рекурсивных функций для уменьшения избыточности, и я не совсем уверен, как я могу превратить окончательный «(a/b)% b == 0» в рекурсию. Я попытался:

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

Но это просто возвращает Нет.

Каков правильный способ рекурсии этой функции?

+3

вы должны учитывать, что значение оператора «/» изменилось в Python 3+, от возвращения целого числа к возврату float, поэтому ваш код сломается. Вместо этого измените его на '//', который всегда будет возвращать int. –

+2

Обратите внимание, что ваша первая попытка не проверяет, является ли a степенью b, она говорит, если a кратно b^2. try isPower (12,2), он вернет True. – Javier

+0

Просто так сказано, ваша первая версия isPower сломана - она ​​покажет только, является ли 'a' кратным' b^2'. Он вернет true для 'isPower (2, 1)', например, который никогда не должен быть правдой. В этом случае вы можете захотеть убедиться, что любая рекурсивная версия проверяет, будет ли '(b == 1 && a! = 1)' до ее продолжения, или она либо застрянет в бесконечном цикле, либо вернет неправильную вещь. – cHao

ответ

3

Вы забываете базовый случай, когда == 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 

Однако это имеет некоторые другие проблемы - если a равно 0, то он никогда не завершится, и если b равно 0, вы получите разделитель на ноль.

Вот многословным решение, насколько я могу сказать, будет работать для всех комбинаций целочисленных:

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: Мой код не работает в тех случаях, когда одновременно и Ь отрицательны. Сейчас я сравниваю их абсолютные значения.

EDIT2: Глупый me, x^0 == 1, поэтому a == 1 ВСЕГДА вернет true. Это также означает, что мне не нужно сравнивать a с b перед рекурсией. Спасибо @ Javier.

+0

Спасибо. Это прояснило именно то, чего мне не хватало. Еще немного поработав с ним, я достиг максимального цикла рекурсии, но не мог понять, как остановить его. Полагаю, я предполагал, что интерпретатор будет знать, что я просто хотел, чтобы он остановился после того, как снова исполнил себя. Теперь я понимаю, что при написании рекурсивного вызова один из тестов позволяет даже разрешить доступ к этой ветви ELIF, чтобы остановить ее. Это была просто практическая функция, поэтому создание базы из 1 было бы неплохо, но спасибо за то, что вы помогли! – bobby

+1

Эй, рад, что я мог бы помочь! Всегда помните, что для всех рекурсивных функций требуются две вещи: базовый регистр (ы) и рекурсивный вызов. Иногда (например, в этом случае) существует более одного базового варианта. –

2

вам нужен еще один случай, когда для обоих условными возвращают ложные

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

Я думаю, что вы имели в виду% b, а не a & b – Bob

+0

Это всегда будет возвращать false. –

+0

На самом деле вам тоже нужно учитывать базовый случай. Я только что отредактировал опечатку. –

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

Это всегда будет возвращать true в том случае, если a изначально 1, однако это только тот случай, если b равно 1 или -1. –

+0

Спасибо за вашу помощь, Хавьер. Ваши ответы и ответы Ники были именно тем, что мне нужно для всего, чтобы щелкнуть в моей голове. Я понимаю важность строительных лесов и написания чрезмерно многословного кода с большим количеством тестов на этом пути, но как только мне будет удобно синтаксис и логика, я хотел бы иметь возможность создавать самый короткий код, который дает тот же эффект. Этот ответ был замечательным, чтобы увидеть, как ответ Ники выглядит как однострочный для дальнейшего использования. Жаль, что у меня нет двух принятых ответов! – bobby

+0

@Niki Yoshiuchi: 1 - сила любого числа (x^0 = 1 для любого x) – Javier

0

попробовать это,

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

объяснение поможет этому ответу – dove

1

Вот мой код. Из того, что я испытал, это работает:

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

Вот мой ответ, это немного чище:

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 
Смежные вопросы