Обновление
Причина, по которой ваш цикл не останавливается, заключается в том, что вы не уделяете ему достаточно времени. То, что вы забыли, так это то, что вы имеете дело с типом decimal
. Использование ==
со значениями decimal
всегда опасно. Тип decimal
является точным (по умолчанию) для 28 мест, что означает, что вы пытаетесь найти чрезвычайно хорошее приближение для этой задачи, потому что только при правильном значении 28 десятичных знаков (current_savings>downpayment or current_savings<downpayment)
оценит на False
, ссылаясь на ваше условие выхода.
По сути, проблема, которая вызывает вашу проблему, заключается в том, что даже когда вы в конечном итоге получаете оценку в 1 000 000,0000000001, Python говорит, что она не равна 1 000 000,0000000000, поэтому он продолжает работать до тех пор, пока не получит следующий 0, а затем просто добавляет еще один ноль. и так далее. Это будет продолжаться в течение очень очень долгого времени и в редких случаях может никогда не остановиться из-за того, что не все десятичные числа могут быть сохранены как двоичные числа (1 000 000 не входит в число этих случаев).
Так, как мы решаем это? Есть два варианта. Самый простой способ - игнорировать центы и просто привести свои значения сравнения к int
, это гарантирует, что любое значение, меньшее доли доллара, будет принято. Другими вариантами является создание диапазона принятых ответов. Скажем, например, я хотел бы сэкономить ровно 1 миллион долларов за эти 36 месяцев, но это вряд ли произойдет. Поэтому вместо этого я согласен на любую сумму в диапазоне от 1 000 000,00 до 1 000 010 долларов (например). Таким образом, мы гарантируем, что любое слишком высокое предположение будет отклонено, и только очень ограниченное количество предположений будет принято.
Независимо от того, по какому маршруту вы идете, обычно рекомендуется поставить условие выхода бесконечного цикла наверх, таким образом вы гарантируете, что оно всегда будет оцениваться.
Мое предложение было бы написать такую функцию и использовать ее в качестве условия для выхода из цикла (который вы поместили бы вверху):
def are_decimals_equal(a, b):
accuracy = 0.0001
return abs(a-b) < accuracy
Это будет считать 0,00009 (и все десятичные дроби меньше этого) равным 0,0000.
Оригинал
Во-первых, как примечание, то, что вы делаете, не называется бисекцией, это называется бинарным поиском.
Теперь к проблеме, вы никогда не меняете значение месяца в своем основном цикле. Это означает, что как только current_savings>downpayment
оценивается как False, ваша программа переходит в бесконечный цикл, поскольку ни одно из условий после того, как оно не может быть оценено как True, как month>=36
всегда будет False.
Из того, что я вижу, во второй части ваших условий в выражениях if / elif нет необходимости, ваши calSavings всегда будут рассчитывать 36-месячные сбережения, никогда больше, никогда. Таким образом, если вы удалите это условие из своих операторов if / elif, ваша программа в конечном итоге остановится, и в этот момент она должна принять правильный ответ.
Наконец, причина, по которой вы видите 0
в качестве результата, заключается в вашем делении в конце. Если вы сделаете print(typeof(guess))
, то увидите, что это целое число, 100 также является целым числом, поэтому это деление приведет к некоторому значению, например 0.3123
, которое будет усечено до 0
. Измените ваш вывод на float(guess/100)
, и это исчезнет.