0

So I'm trying to make a graph of income earned over a period of time with a 'raise' included.

Ex. I earn $100 in a year with a 1% (non-compounding) raise every year. The graph will show total earned income every year for the next 50 years or so. So, 100, 201, 303 etc.

My question is, why do all these equations come out with almost the same, but not exact answers. I'm guessing my logic is prob wrong, but I've been stuck on this for like 2 weeks and can't see my error.


//This adds the income from 3 months at 1% to another 12 months at 1%

console.log(interestCalc(100.00 * (3.00/12), (1.00/365), ((365.00/12) * 3)) + interestCalc(100.00, (1.00/365), ((365.00/12) * 3) + 365));

//This adds the income from 4 months at 1% to another 11 months at 1%

console.log(interestCalc(100.00 * (4.00/12), (1.00/365), ((365.00/12) * 4)) + interestCalc(100.00 * (11.00/12), (1.00/365), ((365.00/12) * 4) + ((365.00/12) * 11)));

//This adds the income from 10 months at 1% to another 5 months at 1%   

console.log(interestCalc(100.00 * (10.00/12), (1.00/365), ((365.00/12) * 10)) + interestCalc(100.00 * (5.00/12), (1.00/365), ((365.00/12) * 10) + ((365.00/12) * 5)));

//This adds the income from 12 months at 1% to another 3 months at 1%

console.log(interestCalc(100.00, (1.00/365), 365) + interestCalc(100.00 * (3.00/12), (1.00/365), 365 + ((365.00/12) * 3)));


function interestCalc(principal, interestRate, time)
{
  interestRate = interestRate * 0.01;

  return principal + (principal * interestRate * time);
}

-------------------------------------------------------------------

Results:

126.3125

126.25694444444443

126.2152777777778

126.3125

Considering all of the equations should be giving the income for a 15 month period of time, I don't understand why they all aren't 126.3125. Any help would be greatly appreciated. I figure i'm just being stupid somehow here, so go ahead and rip into me lol.

giser_yugang
  • 6,058
  • 4
  • 21
  • 44
NPC
  • 31
  • 1
  • 3
  • 1
    There is likely nothing wrong with your math. Check this answer: https://stackoverflow.com/a/588014/4259181 – SoKeT Apr 19 '19 at 02:37
  • actually, @SoKeT, the imprecision in floating point is not relevant to this at all. You'd expect (if the initial premise of the code was right) maybe `0.00000000001` difference, not almost `0.1`! – Jaromanda X Apr 19 '19 at 04:25
  • Please explain how your code relates to the question? you talk about annual income with 1% increase every year, and then your code splits 15 months into two parts, and applies 0.00274% (why are you dividing 1 by 365 if the annual increase is 1) to BOTH parts (why would both parts include the same rate)! – Jaromanda X Apr 19 '19 at 06:50

1 Answers1

2

Let's rearrange your inputs a bit first and make it "DRY"

Since the purpose of time is the number of days (using whole months), then pass in the number of months, and let the function multiply this by 365 / 12 - in the function it's 365 / 1200 because that also handles dividing the interest rate by 100

The principal in your calculation is also multiplied by a number of months, so lets pass this number, 3 and 12 for the first, 4 and 11 for the second etc, and the function will now handle that too - that's the last * m / 12.0 in the function, by the way

//This adds the income from 3 months at 1% to another 12 months at 1%

console.log(
    interestCalc(100.00, 3,  (1.00/365), 3) + 
    interestCalc(100.00, 12, (1.00/365), 15)
);

//This adds the income from 4 months at 1% to another 11 months at 1%

console.log(
    interestCalc(100.00, 4, (1.00/365), 4) + 
    interestCalc(100.00, 11, (1.00/365), 15)
);

//This adds the income from 10 months at 1% to another 5 months at 1%   

console.log(
    interestCalc(100.00, 10, (1.00/365), 10) + 
    interestCalc(100.00, 5, (1.00/365), 15)
);

//This adds the income from 12 months at 1% to another 3 months at 1%

console.log(
    interestCalc(100.00, 12, (1.00/365), 12) + 
    interestCalc(100.00,  3, (1.00/365), 15)
);


function interestCalc(principal, m, interestRate, time)
{
  return (principal + (principal * interestRate * time * 365 / 1200)) * m / 12.0;
}

This outputs the same as your code (except for the least significant digit, because of the order of operations and the fact that floating point in javascript is like any other floating point - but this is insignificant to the problem)

Now, lets simplify

Remove the constants, as they are ... constant

function interestCalc(principal, m, interestRate, time)
{
  return (principal + (principal * interestRate * time)) * m;
}

since interestRate and the way I wrote it, principal, are always the same, remove them

function interestCalc(principal, m, interestRate, time)
{
  return time * m;
}

So, now, the results are

 3 *  3 + 12 * 15 === 189
 4 *  4 + 11 * 15 === 181
10 * 10 +  5 * 15 === 175
12 * 12 +  3 * 15 === 189

You can see your calculations are flawed if you think all 4 will have the same result

It's also apparent that the two calculations that match are also actually wrong

Having said that, I haven't tried to figure out the correct formula, because I'm not exactly sure what you are trying to achieve

Having read the question again, I can't see how your code even relates to what you're trying to achieve

I'm assuming this is what you wanted to do - that you want to calculate wages when an increase happens after 3, 4, 10 or 12 months - i.e. the wage increase could be part way into the year

with no increase, 100 per annum for 15 months would be 100 * 15 / 12 = 125

So, each split should produce a value above 125 (because of the increase) but as you have more time at the lower rate, the values would get closer to 125

You would expect the maximum over 15 months to be 25 for the first 3 months plus 101 for the next 12 months

The minimum would be 100 for 12 months + 101/4 for 3 months 25.25 for a total of 125.25

So, all calculations MUST fall between 125.25 and 126.00

using my code above, and changing interestCalc function:

console.log(
    interestCalc(100.00,  3, 0) + 
    interestCalc(100.00, 12, 1)
);

console.log(
    interestCalc(100.00,  4, 0) + 
    interestCalc(100.00, 11, 1)
);

console.log(
    interestCalc(100.00, 10, 0) + 
    interestCalc(100.00,  5, 1)
);

console.log(
    interestCalc(100.00, 12, 0) + 
    interestCalc(100.00,  3, 1)
);


function interestCalc(principal, time, interestRate) {
    return (principal + principal * interestRate / 100) * time / 12;
}

As you can see, they all fall in that range

Now, lets make this a little smarter

console.log(calc(100,  3, 1, 15));
console.log(calc(100,  4, 1, 15));
console.log(calc(100, 10, 1, 15));
console.log(calc(100, 12, 1, 15));

function calc(base, firstYearMonths, increase, totalMonths) {
    return (base * firstYearMonths / 12) + (base * (increase + 100) / 100 * (totalMonths - firstYearMonths) / 12);
}

But this only allows from 12 to 23 total months

So, lets make it smarter still, because now we can even manage two or more increases (i.e. span 2 or more wage increases)

console.log(calc(100,  3, 1, 15));
console.log(calc(100,  4, 1, 15));
console.log(calc(100, 10, 1, 15));
console.log(calc(100, 12, 1, 15));

function calc(base, firstYearMonths, increase, totalMonths) {
    let ret = base * firstYearMonths / 12;
    totalMonths -= firstYearMonths;
    let year = 1;
    while(totalMonths > 0) {
        ret += base * (1 + (increase * year) / 100) * Math.min(totalMonths, 12) / 12;
        totalMonths -= 12;
        year += 1;
    }
    return ret;
}
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87