How do I find the LOWEST FIXED monthly payment in 2 dp to pay off the balance with compounded interest for 12 months using bisection in ruby?
Disclaimer: I am applying upperBound and unpaidBalance formula correctly.
Test case:
find_fixed_payment(320000, 0.2) should return 29157.09
But my current method returns the middle value of 29591.87 which is way more than enough as the fixed payment (need to reduce to the lowest).
Where did my code went wrong as I am not sure how to do bisection (im using binary search)?
def find_fixed_payment(balance,annualInterestRate)
lowerBound = balance/12
upperBound = (balance * (1 + annualInterestRate/12)**12) / 12.0
unpaidBalance = balance
while true
middle = (lowerBound + upperBound )/2
#use middle as the monthly payment at first
(1..12).each do |i|
unpaidBalance = (unpaidBalance - middle) +
annualInterestRate / 12 * (unpaidBalance - middle)
end
temp = unpaidBalance.floor
if temp < 0
middle -= 0.01
upperBound = middle
# should go to for loop to reduce unpaid balance
# with new middle but not happening, why?
else
middle += 0.01
lowerBound = middle
end
if temp == 0
return middle
end
if upperBound == lower+1
return -1
end
return middle.round(2)
end
end
You made a lot of errors, I'm assuming you were transcribing this method from a reading somewhere, and simply failed to understand the process it was describing.
Basically you initialize all your starting variables, then you need the create the loop. Once in the loop, each time through you're calculating, you'll need to reset the balance back to 320,000 or it becomes a bit of a moving target and we'll never get the answer you're looking for.
I used the times method on the integer 12 to simulate the 12 month cycle, in your attempt you used a range and called the each method.
Now, I'm not sure why you were trying to adjust the value of middle like that, but it was a moot point because once it looped back to the beginning of your while true
loop, it just went back to the original middle value. In my version I changed the upper or lower bound appropriately. Think of it like a number guessing of 1-10, you're smart enough to know you just pick the middle every time until you get it, and you would start with a lower bound of 1 and upper of 10, then guess 5. If I told you higher, you now know that 5 is your lower and 10 is still your upper.
Note: I hope this helps, and welcome other users feel free to critique and refactor my code, I only started ruby recently.
def find_fixed_payment(balance,annualInterestRate)
monthlyInterestRate = annualInterestRate / 12
lowerBound = balance/12
upperBound = (balance * (1 + monthlyInterestRate)**12) / 12.0
unpaidBalance = balance
accuracy = 0.01
while unpaidBalance.abs > accuracy
balance = unpaidBalance
middle = (lowerBound + upperBound) / 2
12.times do
newUnpaidBalance = unpaidBalance - middle
monthInterest = monthlyInterestRate * newUnpaidBalance
unpaidBalance = newUnpaidBalance + monthInterest
end
if unpaidBalance < 0
upperBound = middle
unpaidBalance = balance
elsif unpaidBalance > accuracy
lowerBound = middle
unpaidBalance = balance
end
end
middle.round(2)
end
find_fixed_payment(320000, 0.2)