9

I have to write 6 small JavaScript scripts for school and I've got them all working apart from this one.

function calculate() {
    var numbers = [
        document.getElementById("num_one").value ,
        document.getElementById("num_two").value ,
        document.getElementById("num_three").value 
    ];
    var sum = numbers[0] + numbers[1] + numbers[2];
    document.getElementById("display_sum").innerHTML = sum;
}

The user is supposed to enter 3 numbers click a button and it should add them all togther or "find the sum".

My Problem is, it just joins the numbers togther instead of adding them. Does anyone know a way to fix this?

Craig Harkins
  • 153
  • 2
  • 10

11 Answers11

16

You are "summing" string variables so Javascript is concatenating them.

You need to convert them to numbers in order to have an arithmetic sum:

function calculate() {
        var numbers = [
            document.getElementById("num_one").value ,
            document.getElementById("num_two").value ,
            document.getElementById("num_three").value 
        ];
        var sum = Number(numbers[0]) + Number(numbers[1]) + Number(numbers[2]);
        document.getElementById("display_sum").innerHTML = sum;
        }
Juan
  • 3,675
  • 20
  • 34
7

Parse string using parseFloat(), parseInt() or Number(), for converting it's to number. Otherwise + will just do string concatenation , since the values are string.

function calculate() {
  var numbers = [
    document.getElementById("num_one").value,
    document.getElementById("num_two").value,
    document.getElementById("num_three").value
  ];
  var sum = parseFloat(numbers[0]) + parseFloat(numbers[1],) + parseFloat(numbers[2]);
  document.getElementById("display_sum").innerHTML = sum;
}

function calculate() {
  var numbers = [
    document.getElementById("num_one").value,
    document.getElementById("num_two").value,
    document.getElementById("num_three").value
  ];
  var sum = Number(numbers[0]) + Number(numbers[1]) + Number(numbers[2]);
  document.getElementById("display_sum").innerHTML = sum;
}

function calculate() {
  var numbers = [
    document.getElementById("num_one").value,
    document.getElementById("num_two").value,
    document.getElementById("num_three").value
  ];
  var sum = parseInt(numbers[0], 10) + parseInt(numbers[1], 10) + parseInt(numbers[2], 10);
  document.getElementById("display_sum").innerHTML = sum;
}
Pranav C Balan
  • 113,687
  • 23
  • 165
  • 188
4

The value property is string. In order to use it in arithmetic operations, you need to parse it to integers. The simpliest way to do this in JS is +x. You can use Array.prototype.map and Array.prototype.reduce to make it easier:

var ids = ['num_one', 'num_two', 'num_three'];
var sum = ids
    .map(function(x) { return +document.getElementById(x).value; })
    .reduce(function(a,b) { return a+b; }, 0);

With this way, you will be able to introduce new elements into calculations with minimal changes.

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
  • 1
    Why the extra call for `.map()`? The query part can be moved into the `.reduce()` call. The array is small but why iterate the array(s) twice? – Andreas Nov 12 '15 at 11:48
  • 2
    @Andreas if performance isn't a concern, IMHO it's cleaner to separate the functionality of extracting the values from the subsequent addition of them – Alnitak Nov 12 '15 at 14:10
2

.value return String you need convert it to Number,

you can do it with parseInt or parseFloat(if you have float values), or with Number() or just add + before value

var numbers = [
    +document.getElementById("num_one").value,
    +document.getElementById("num_two").value,
    +document.getElementById("num_three").value
];

or

var numbers = [
   Number(document.getElementById("num_one").value),
   Number(document.getElementById("num_two").value),
   Number(document.getElementById("num_three").value)
];

or

var numbers = [
   parseInt(document.getElementById("num_one").value, 10),
   parseInt(document.getElementById("num_two").value, 10),
   parseInt(document.getElementById("num_three").value, 10)
];
Oleksandr T.
  • 76,493
  • 17
  • 173
  • 144
2

The shortest approach is to use Array.prototype.map

The map() method creates a new array with the results of calling a provided function on every element in this array.

in combination with Number

The Number JavaScript object is a wrapper object allowing you to work with numerical values. A Number object is created using the Number() constructor.

The primary uses for the Number object are:

  • If the argument cannot be converted into a number, it returns NaN.
  • In a non-constructor context (i.e., without the new operator), Number can be used to perform a type conversion.

and then Array.prototype.reduce

The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.

in combination with a callback like

function (a, b) {
    return a + b;
}

Together in a single line with your code wrapped:

function calculate() {
    var numbers = [
            document.getElementById("num_one").value,
            document.getElementById("num_two").value,
            document.getElementById("num_three").value
        ],
        sum = numbers.map(Number).reduce(function (a, b) { return a + b; });
    document.getElementById("display_sum").innerHTML = sum;
}
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • There must be a way to use `map()` to populate the `numbers` array in the first place, too, even though the OP didn't ask for that... – david Nov 12 '15 at 18:32
2

A scalable solution in one line of es6:

var sum = numbers.reduce((a, b) => Number(a) + Number(b), 0);

Be sure to include an initialValue at the end there - it'll guarantee the callback is executed and a number is returned in cases where the array contains no values/one value.

More info on reduce

dsgriffin
  • 66,495
  • 17
  • 137
  • 137
  • don't forget to include the trailing `0` argument, otherwise `reduce` will fail unless there's at least two elements in the array. – Alnitak Nov 12 '15 at 13:47
  • @Alnitak Seems to work with one element, although fails if empty – dsgriffin Nov 12 '15 at 13:57
  • 1
    ah yes - I didn't quite remember the rules properly. If there's only one element, it returns it without invoking the callback [implying that you'll still get a string in this case, not a number]. Hence you should still supply the zero to ensure that the callback is invoked to apply the conversion. – Alnitak Nov 12 '15 at 14:05
  • @Alnitak True, in OP's particular example returning a string to innerHTML shouldn't matter but I'll update it for general use case – dsgriffin Nov 12 '15 at 14:11
  • also (not withstanding performance), how about `var sum = numbers.map(Number).reduce((a, b) => a + b, 0)` – Alnitak Nov 12 '15 at 14:13
  • @Alnitak I originally had something similar to that but felt it would be less efficient :/ – dsgriffin Nov 12 '15 at 14:16
  • yes, it is strictly slightly less efficient, but it's not like this code is in a tight loop anywhere. It's certainly cleaner, though, since it completely separates the type conversions from the additions. On the flip side, `Number(a) + Number(b)` does make it clear that we are in fact doing addition and not concatenation :/ – Alnitak Nov 12 '15 at 14:17
1

Depending on whether your input numbers are integers or decimals, you can use parseInt or parseFloat.

xaviert
  • 5,653
  • 6
  • 29
  • 31
1

There are already plenty of reasonable answers, but here's a neat shorthand alternative:

var sum = +numbers[0] + +numbers[1] + +numbers[2];
Chris Lear
  • 6,592
  • 1
  • 18
  • 26
1

By default, javascript treats input values as strings. So you have to manually convert them to integers like this:

var numbers = [
    document.getElementById("num_one").value ,
    document.getElementById("num_two").value ,
    document.getElementById("num_three").value 
];

document.getElementById("display_sum").innerHTML =
    numbers
        .reduce(function(sum, element) { return sum + parseInt(element, 10);}, 0);

What is good about this code, is that if you need to calculate for more than three elements you only need to modify your numbers array.

Eternal1
  • 5,447
  • 3
  • 30
  • 45
1

I think you can use an array to store the inputs like

<script>
var numbers;

function push(){
  numbers.push(getDocumentById("someid").val;
}


function calculate(){
  var sum=0;
  for(i=0; i<numbers.len; i++){
    sum=sum + numbers[i];
  }
    alert(sum);
}

</script>

<div>
  <button id="someid" value=20 onClick="addToArray();">click to push</button>
</div>

<div>
  <button id="calc" onClick="calculate();">click to calculate</button>
</div>
Abhishek Dhanraj Shahdeo
  • 1,356
  • 2
  • 14
  • 35
1

The following will solve the problems:

function calculate() {
var numbers = [
    +(document.getElementById("num_one").value) ,
    +(document.getElementById("num_two").value) ,
    +(document.getElementById("num_three").value) 
];
var sum = numbers[0] + numbers[1] + numbers[2];
document.getElementById("display_sum").innerHTML = sum;
}