Вопрос: Годовая выплата долга, MIT edX 6.001 U2 / PS2 / P1

Напишите программу для расчета баланса кредитной карты через год, если человек платит только минимальный ежемесячный платеж, требуемый компанией-эмитентом кредитной карты каждый месяц.

Следующие переменные содержат значения, как описано ниже:

balance — непогашенный остаток по кредитной карте

annualInterestRate — годовая процентная ставка в виде десятичной дроби

monthlyPaymentRate — минимальная ежемесячная ставка платежа в виде десятичной дроби

За каждый месяц рассчитывайте выписки по ежемесячному платежу и остатку. По истечении 12 месяцев распечатайте остаток. Обязательно распечатайте не более двух десятичных знаков точности — так что печатайте

Remaining balance: 813.41

вместо

Remaining balance: 813.4141998135

Таким образом, ваша программа выводит только одно: остаток на конец года в формате:

Remaining balance: 4784.0

Краткое изложение требуемой математики можно найти ниже:

begin {align *} text {Ежемесячная процентная ставка} & = frac { text {Годовая процентная ставка}} {12} \ text {Минимальный ежемесячный платеж} & = text {Минимальная ежемесячная ставка платежа} times text {Предыдущий остаток} \ text {Ежемесячный невыплаченный остаток} & = text {Предыдущий остаток} \ & — text {Минимальный ежемесячный платеж} \ text {Обновляемый остаток каждый месяц} & = text {Ежемесячно невыплаченный остаток} \ & + ( text {Ежемесячная процентная ставка} times text {Ежемесячный невыплаченный остаток}) end {align *}

Код

def balances(initial_balance, annual_interest_rate, minimum_monthly_payment_rate):
    balance = initial_balance
    monthly_interest_rate = annual_interest_rate / 12

    for month in range(13):
        minimum_monthly_payment = balance * minimum_monthly_payment_rate

        monthly_unpaid_balance = balance - minimum_monthly_payment 

        yield {'month': month,
               'minimum_monthly_payment': minimum_monthly_payment,
               'balance': balance}

        balance = monthly_unpaid_balance + (monthly_unpaid_balance * monthly_interest_rate)

def main():
    *bs, remaining_balance = balances(balance, annualInterestRate, monthlyPaymentRate)
    print('Remaining Balance: {}'.format(round(remaining_balance['balance'], 2)))

# Testing data
balance = 484
annualInterestRate = .2
monthlyPaymentRate = .04

## ifname_main does not work in grader
if __name__ == '__main__':
    main()

Заранее спасибо.

2 ответа
2

  • Можно использовать подсказки типа PEP484
  • range(13) неудобно — нет смысла возвращать начальный баланс, поэтому просто выведите скорректированные остатки и сделайте это 12 раз
  • Нет смысла сдавать месяц, платеж и баланс; просто уступите баланс. Даже если вам нужно было найти все три, словарь — не лучший способ сделать это. Кортежи стандартные; или класс данных лучше структурирован.
  • Не надо звонить format или же round. Просто используйте .2f. Обратите внимание, что это противоречит спецификации Remaining balance: 4784.0 но это глупо; это денежная сумма, поэтому точность должна быть фиксированной.
  • Ваш balances хорош как генератор, но зачем ограничивать его до 12 итераций? Более общая и полезная реализация просто повторяется бесконечно. Использовать islice вывести 12 значений, игнорируя все, кроме последнего.

Предлагаемый (итеративный)

from itertools import islice
from typing import Iterable


def balances(
    initial_balance: float,
    annual_interest_rate: float,
    minimum_monthly_payment_rate: float,
) -> Iterable[float]:
    balance = initial_balance
    monthly_interest_rate = annual_interest_rate / 12

    while True:
        minimum_monthly_payment = balance * minimum_monthly_payment_rate
        monthly_unpaid_balance = balance - minimum_monthly_payment
        balance = monthly_unpaid_balance * (1 + monthly_interest_rate)
        yield balance


def main():
    for balance in islice(
        balances(
            initial_balance=484.00,
            annual_interest_rate=0.20,
            minimum_monthly_payment_rate=0.04,
        ),
        12,
    ):
        pass

    print(f'Remaining Balance: {balance:.2f}')


if __name__ == '__main__':
    main()

Упрощение внутреннего цикла заменило бы его на

balance *= (1 - minimum_monthly_payment_rate) * (1 + monthly_interest_rate)

что эквивалентно.

Предлагаемый (составной)

Еще лучше полностью избавиться от цикла и просто использовать мощность:

def compound(
    initial_balance: float,
    annual_interest_rate: float,
    minimum_monthly_payment_rate: float,
    months: int,
) -> float:
    monthly_interest_rate = annual_interest_rate / 12

    return initial_balance * (
        (1 - minimum_monthly_payment_rate) * (1 + monthly_interest_rate)
    ) ** months


def main():
    balance = compound(
        initial_balance=484.00,
        annual_interest_rate=0.20,
        minimum_monthly_payment_rate=0.04,
        months=12,
    )

    print(f'Remaining Balance: {balance:.2f}')


if __name__ == '__main__':
    main()

  • Разве не было бы бесполезно давать отрицательный баланс? Может быть, сделай это while balance >= 0

    — РэкетирHaskeller

  • Возможный. Добавьте это, если хотите. Существуют некоторые типы счетов (без кредитных карт), для которых было бы полезно иметь возможность отображать как кредитное, так и дебетовое состояние.

    — Райндериен

  • Тем не менее, сделайте небольшую математику, и вы обнаружите, что баланс никогда не опускается до нуля или ниже нуля за конечное количество итераций.

    — Райндериен

В balances функция немного длинная. Содержимое цикла может быть другой функцией. Эта функция отвечает за выполнение этого требования:

За каждый месяц рассчитывайте выписки по ежемесячному платежу и остатку

Вместо yield-создание конструкции с month, minimum_monthly_payment, а также balance для каждой итерации цикла вы можете return в конце петли. Фактически, month а также minimum_monthly_payment не используется вообще, поэтому вы можете вернуть только оставшиеся balance в конце 12 месяцев.

Поскольку balances функция теперь возвращает только одно число, вы можете избавиться от сложного кода на main. Просто возьмите этот номер и распечатайте его.

После этих изменений переименуйте balances метод к чему-то более значимому.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *