0

I am trying to do math with Javascript, it will run calculation from one input (monthly salary) to result (tax) as following:

  • Deduction from annual income (12000)
  • here comes the hard part, tax is calculated in different levels, so if annual is between 6500 and 25000, tax should be 10%. And if there is more left after 25000 and less than 40000, tax should be 15% added to the previous 10%, and so on.

EX. if annual is 60000, the math will be like this:

 60000 - 12000 = 48000 // deduction
 25000 X (10/100)   = 2500 // 10% tax on 6500-25000 range
 48000 - 25000 = 23000 // first cut 25000
 23000 X (15/100) = 3450 // 15% tax on 25000-40000 range
 total tax will be 2500 + 3450 = 5950

Code:

<input type=text id="salary">
<div id="total"></div>
<script>
function calc(){
    var salary   = document.getElementById('salary').value;
    var annual   = salary * 12;
    var net      = annual - 12000;
    // Define Tax brackets
    var bracket1 = (10 / 100);
    var bracket2 = (15 / 100);
    if (net >= 6500){
        if ( net >= 6500 && net <= 25000 ) {
           var tax1 = (net * bracket1);
        }
        else if ( net >= 30000 && net <= 40000 ) {
           var tax2 = (net * bracket2);
        }

        var result = (tax1 + tax2) / 12; //monthly tax

    document.getElementById('total').innerHTML = result ;

}
</script>

So output comes as NaN, I am not sure if what I have done so far is the right thing or variables inside statement is the problem here.

Kareem
  • 55
  • 1
  • 8
  • Your function is missing a closing bracket. And in `else if (net = 30000` you probably meant `else if (net == 30000` – j08691 Sep 08 '15 at 13:38
  • You missed a closing bracket. Make sure salary is a number, and not string: var salary = parseInt( document.getElementById('salary').value , 10 ); – javifm Sep 08 '15 at 13:40
  • @puro_nervio probably need to use `parseFloat()` because salary might have a fractional part – Pointy Sep 08 '15 at 13:41
  • Yes @Pointy, probably yes. The example was and integer. – javifm Sep 08 '15 at 13:43
  • Missing else condition as well... – Rayon Sep 08 '15 at 13:44
  • your vars are scoped inside the ifs. If you don't pass in the if, the var is not declared at all – njzk2 Sep 08 '15 at 13:45
  • `tax1` and `tax2` are never defined at the same time. – Teemu Sep 08 '15 at 13:45
  • 2
    also, use a debugger. There is one in every browser – njzk2 Sep 08 '15 at 13:46
  • @njzk2 A block scope in JS is defined with `let` (ES6 only). – Teemu Sep 08 '15 at 13:46
  • well, I am not sure where that bracket start at, it works fine if the calculation is outside the if statements. – Kareem Sep 08 '15 at 13:54
  • 1
    The line `if (net==30000 && net <= 40000)` makes no logical sense, too (still, the missing bracket, the scope problems, and so on). Declare your vars outside (this case, global scope) the way they are now the code can't reach their value outside the if's – lockedz Sep 08 '15 at 13:57
  • @Kareem In the post there's missing `>` in the if condition (should be `else if ( net >= 30000 && net <= 40000 )`). Also `if-else` structure omits either the assignment of `tax1` or `tax2`, depending on the entered value. Despite of missing assignment, you're doing some math with both of these variables. You've to initialize these variables with a value before the `if-else`, like Rayon Dabre has done in their answer. – Teemu Sep 08 '15 at 13:58
  • @Teemu `scope` was the wrong word. What I meant was that if the if is not executed, the the variable is undefined (although the reference does exist, since there is indeed no scope) – njzk2 Sep 08 '15 at 15:14
  • @Kareem you don't really need all those ifs. For example, the tax brackets can be computed directly: `var tax1 = bracket1 * Math.min(25000, net); var tax2 = bracket2* Math.min((40000 - 25000), net - 25000);`... Each bracket should have a rate and a range. (1 -> 10%, (0-25000), 2 -> 15%, (25000, 40000)). You can then loop on the brackets and simply apply the values to accumulate the total tax. – njzk2 Sep 08 '15 at 15:21

2 Answers2

0

The algorithm itself seems to be... buggy (you might want to review it), but, assuming some things myself, this works. Try running it and see what you can improve.

<html>
<head>
<title>TAX</title>
</head>

<script type="text/javascript">
function calc(){
    var result, tax1 = 0, tax2 = 0;

    var salary   = document.getElementById('salary').value;
    var annual   = salary * 12;
    var net      = annual - 12000;

    // Define Tax brackets
    var bracket1 = (10 / 100);
    var bracket2 = (15 / 100);

    if (net >= 6500) {
        if (net >= 6500 && net <= 25000) {
            tax1 = (net * bracket1);
        }
        else if (net >= 30000 && net <= 40000) {
            tax2 = (net * bracket2);
        }
        result = (tax1 + tax2) / 12; // monthly tax
    }

    document.getElementById('total').innerHTML = result;
    console.log(result);
}
</script>
<body>

<input type=text id="salary" onblur="calc();" value="0" />
<div id="total"></div>
</body>
</html>

There was a missing }; using var inside the if declarations is not a common practice, so I declared them in a bigger scope (calc() for this matter); I assumed the line if (net = 30000 && net <= 40000) was about net >= 30000, but... your call; The way it is now, either tax1 or tax2 will be setted. One of them will be zero. That's because of the if/else statements, they are confusing.

ps.: also, you might wanna use the parseFloat, as stated by some, considering the 'incoming' is not always an integer; pps: I added a value="" in the input so it is - somewhat - defined at all times.

lockedz
  • 219
  • 6
  • 15
  • @Teemu woah, calm down, cowboy. Do you really think it's clever (language independent) to declare the `var` inside the specific `if/else` statement, nonetheless? – lockedz Sep 08 '15 at 14:13
  • No, it's not clever, and you've fixed that issue in your code correctly, but the explanation is blatantly wrong. – Teemu Sep 08 '15 at 14:14
  • @Teemu yes, my fault in this, I meant "globals". As a bigger scope – lockedz Sep 08 '15 at 14:14
  • Well, @Kareem, them you might wan't to read this anwser: http://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript?rq=1 – lockedz Sep 08 '15 at 14:16
  • @Teemo feel free to edit my code. Maybe I've been spending too little time with Javascript to remember it corretcly. Thanks for pointing these out, tho. – lockedz Sep 08 '15 at 14:19
  • Well, I'm not going to edit your code, it's OK. Only the explanation is not correct. In JS declared variables are hoisted, and they are getting the value of `undefined` by default. That's what causes `NaN` to OP's results ,when they do `tax1 + tax2`. – Teemu Sep 08 '15 at 14:21
  • Looks like my first comment was flagged and removed. I'm sorry, I didn't mean to be rude. As you've maybe noticed, english is not my native language, I might have used an incorrectly translated word in my comment. From now on, I know not to use it in the context I used it here. – Teemu Sep 08 '15 at 14:36
  • 1
    @Teemu don't worry, it isn't mine neither. And I haven't flagged it, you seem to be very reasonable :). Peace. – lockedz Sep 08 '15 at 14:57
0

With the example given, this code might help you get started on the logic.

function calc(){
  var salary   = document.getElementById('salary').value;
  var annual   = salary * 12;
  var net      = annual - 12000;
  console.log(salary, annual, net);
  // Define Tax brackets
  var bracket1 = (0.1);
  var bracket2 = (0.15);
  var tax1 = 0;
  var tax2 = 0;
  var runningNet = net;
  if (net >= 6500){
    if (net >= 25000) {
      tax1 = 2500; // 2500 * 0.10, max tax on bracket 1
      runningNet = runningNet - 25000;
      tax2 = runningNet * bracket2; // whatever is left over * bracket2
    }
    else {
      tax1 = runningNet * bracket1;
    }        
    var result = (parseFloat(tax1) + parseFloat(tax2));
    var monthly = result / 12; //monthly tax

    document.getElementById('total').innerHTML = result ;
    document.getElementById('monthly').innerHTML = monthly ;

  }
}
<input type="text" id="salary" />
<button type="button" onclick="calc()">Calculate</button>
<br/>
Total: <div id="total"></div>
Monthly: <div id="monthly"></div>
indubitablee
  • 8,136
  • 2
  • 25
  • 49