Пытаюсь заставить поиск по разделению пополам работать, но

#python-3.x #bisection

#python-3.x #разделение пополам

Вопрос:

Я следую MIT OCW 6.0001, и в задаче 1, часть c, мы должны настроить поиск по разделению пополам, чтобы найти наилучшую норму экономии, но мой код работает не так, как я предполагал. Требуется помощь, чтобы разобраться в проблеме.

 total_cost = float(input("Cost of dream house"))
down_payment = total_cost * 0.25
annual_salary = float(input("Annual salary"))
monthly_salary = annual_salary / 12
current_savings = 0

x = 100.0000
low = 0.0000
high = 1.0000
guess = (high   low) / 2

r = 0.04
portion_saved = monthly_salary * guess
semi_annual_raise = (100   100*(float(input("Semi annual raise")))) / 100
number_of_months = 0.00
max_number_of_months = float(input("Max Time (in months)"))

while abs(current_savings - down_payment) > x:
    if current_savings - down_payment > x:
        high = guess
        guess = (high   low) / 2
        portion_saved = monthly_salary * guess
        current_savings = 0
    elif down_payment - current_savings > x:
        low = guess
        guess = (high   low) / 2
        portion_saved = monthly_salary * guess
        current_savings = 0
    else:
        guess = guess
        portion_saved = monthly_salary * guess

    if number_of_months < max_number_of_months and number_of_months % 6 == 0:
        current_savings *= (100   r / 12) / 100
        portion_saved *= semi_annual_raise
        current_savings  = portion_saved
        number_of_months  = 1
    elif number_of_months < max_number_of_months and number_of_months % 6 != 0:
        current_savings *= (100   r / 12) / 100
        current_savings  = portion_saved
        number_of_months  = 1


print(current_savings)
print(number_of_months)
 

Ожидаемый результат: первый оператор if else предоставляет значение guess, которое используется во втором операторе if else, и если оно abs(current_savings — авансовый платеж)> x, цикл выполняется снова, пока abs(current_savings — авансовый платеж) < x.
Фактический результат: программа застряла в бесконечном цикле в первом операторе if.

Ответ №1:

 # data supplied by the user
base_annual_salary = float(input('Enter your annual salary: '))

# data that is fixed
portion_down_payment = 0.25
rate_of_return = 0.04
monthly_rate_of_return = rate_of_return / 12
total_cost = 1000000
down_payment = total_cost * portion_down_payment
semi_annual_raise = 0.07
months = 36

# initially savings are zero. This variable is the core part of the decrementing
# function used to stop the algorithm
current_savings = 0.0

# there is an acceptable margin of error for this algorithm
epsilon = 100

# define high and low bounds for the bisection search
initial_high = 10000
high = initial_high
low = 0
portion_saved = (high   low) // 2
steps = 0

# use bisection search to find the solution
while abs(current_savings - down_payment) > epsilon:
    steps  = 1
    current_savings = 0.0
    annual_salary = base_annual_salary
    monthly_salary = annual_salary / 12
    monthly_deposit = monthly_salary * (portion_saved / 10000)
    for month in range(1, months   1):
        current_savings *= 1   monthly_rate_of_return
        current_savings  = monthly_deposit
        # problem states that semi-annual raises take effect the next month, so 
        # mutate monthly_salary after mutating current_savings
        if month % 6 == 0:
            annual_salary *= 1   semi_annual_raise
            monthly_salary = annual_salary / 12
            monthly_deposit = monthly_salary * (portion_saved / 10000)
    prev_portion_saved = portion_saved
    if current_savings > down_payment:
        high = portion_saved
    else:
        low = portion_saved
    # if the solution is outside of the search space on the high bound, low
    # will eventually equal the inital high value. However, if we use integer
    # division, low will be one less than high. As such, we round the average
    # of high and low and cast to an int so that low and high will converge
    # completely if the solution is outside of the search space on the high
    # bound
    portion_saved = int(round((high   low) / 2))
    # if portion_saved is no longer changing, our search space is no longer
    # changing (because the search value is outside the search space), so we
    # break to stop an infinite loop
    if prev_portion_saved == portion_saved:
        break

if prev_portion_saved == portion_saved and portion_saved == initial_high:
    print('It is not possible to pay the down payment in three years.')
else:
    print('Best savings rate:', portion_saved / 10000)
    print('Steps in bisection search:', steps)
 

Вот ссылка на решения всего этого набора проблем:

https://github.com/kaizenflow/6.0001-ps1

Комментарии:

1. Хотя теоретически это может дать ответ на вопрос, было бы предпочтительнее включить сюда основные части ответа и предоставить ссылку для справки.

Ответ №2:

     """ x = current_savings y = portion_saved z = number_of_months  """
    while x < 250000:
        if z >= 1 and z % 6 == 0:
            x *= (100   4 / 12) / 100
            y *= 1.07
            x  = y
            z  = 1

        else:
            x *= (100   4 / 12) / 100
            x  = y
            z  = 1
    L1 = [x, z]
    return L1


def rate(a, r_rate, lo, hi):
    """ a = number_of_months"""
    if a - 36 > 0:
        lo = r_rate
        r_rate = (hi   lo) / 2.0
        L2 = [r_rate, lo]
        return L2
    else:
        hi = r_rate
        r_rate = (hi   lo) / 2.0
        L3 = [r_rate, hi]
        return L3


total_cost = 1000000
down_payment = total_cost * 0.25
annual_salary = int(input("Annual Salary"))
monthly_salary = annual_salary / 12
current_savings = 0
number_of_months = 0
low = 0.0
high = 1.0
r = 0.5
num_tries = 0

while abs(current_savings - down_payment) > 100:
    portion_saved = monthly_salary * r
    current_savings = 0
    number_of_months = 0
    L5 = [savings(current_savings, portion_saved, number_of_months)[0], savings(current_savings, portion_saved, number_of_months)[1]]
    current_savings = L5[0]
    number_of_months = L5[1]
    L6 = [(rate(number_of_months, r, low, high)[0]), (rate(number_of_months, r, low, high)[1])]
    r = L6[0]
    if number_of_months - 36 > 0:
        low = L6[1]

    else:
        high = L6[1]
    num_tries  = 1


print(r)
print(num_tries)