Home > front end >  Calculating Standard Deviation with JavaScript showing NaN in Textfield
Calculating Standard Deviation with JavaScript showing NaN in Textfield

Time:07-05

so i want to calculate the standard deviation of 10 values from input types. I am collecting them into an array and want to calculate my standard deviation.

Problem is, it always shows NaN when i run the function (with action "oninput")

My code is the following:

function s10() {

                    var n1 = parseFloat(document.getElementById('input1').value);
                    var n2 = parseFloat(document.getElementById('input2').value);
                    var n3 = parseFloat(document.getElementById('input3').value);
                    var n4 = parseFloat(document.getElementById('input4').value);
                    var n5 = parseFloat(document.getElementById('input5').value);
                    var n6 = parseFloat(document.getElementById('input6').value);
                    var n7 = parseFloat(document.getElementById('input7').value);
                    var n8 = parseFloat(document.getElementById('input8').value);
                    var n9 = parseFloat(document.getElementById('input9').value);
                    var n10 = parseFloat(document.getElementById('input10').value);

                    var arr = [{
                        key: 'n1',
                        value: parseFloat(document.getElementById('input1').value)
                    }, {
                        key: 'n2',
                        value: parseFloat(document.getElementById('input2').value)
                    }, {
                        key: 'n3',
                        value: parseFloat(document.getElementById('input3').value)
                    }, {
                        key: 'n4',
                        value: parseFloat(document.getElementById('input4').value)
                    }, {
                        key: 'n5',
                        value: parseFloat(document.getElementById('input5').value)
                    }, {
                        key: 'n6',
                        value: parseFloat(document.getElementById('input6').value)
                    }, {
                        key: 'n7',
                        value: parseFloat(document.getElementById('input7').value)
                    }, {
                        key: 'n8',
                        value: parseFloat(document.getElementById('input8').value)
                    }, {
                        key: 'n9',
                        value: parseFloat(document.getElementById('input9').value)
                    }, {
                        key: 'n10',
                        value: parseFloat(document.getElementById('input10').value)
                    }, ];

                    const mean = arr.reduce((s, n) => s   n) / arr.length;
                    const variance = arr.reduce((s, n) => s   (n - mean) ** 2, 0) / (arr.length - 1);
                    document.getElementById('s').value = Math.sqrt(variance);
                }
<input type="text" id="input1"/>
<input type="text" id="input2"/>
<input type="text" id="input3"/>
<input type="text" id="input4"/>
<input type="text" id="input5"/>
<input type="text" id="input6"/>
<input type="text" id="input7" />
<input type="text" id="input8" />
<input type="text" id="input9" />
<input type="text" id="input10" oninput="s10();" />
<input type="text" id="s" placeholder="standardDeviation" />

CodePudding user response:

Below is a modified example of your code. A couple of notes:

  • When calculating the mean and variance, you were using n in the reduce callbacks, rather than n.value
  • The first reduce function needed an initial value of 0
  • I used number type inputs to make it easier to step through values
  • n.value || 0 will use 0 when the input is empty to prevent errors during addition

<script>
  function s10() {
    var n1 = parseFloat(document.getElementById("input1").value);
    var n2 = parseFloat(document.getElementById("input2").value);
    var n3 = parseFloat(document.getElementById("input3").value);
    var n4 = parseFloat(document.getElementById("input4").value);
    var n5 = parseFloat(document.getElementById("input5").value);
    var n6 = parseFloat(document.getElementById("input6").value);
    var n7 = parseFloat(document.getElementById("input7").value);
    var n8 = parseFloat(document.getElementById("input8").value);
    var n9 = parseFloat(document.getElementById("input9").value);
    var n10 = parseFloat(document.getElementById("input10").value);

    var arr = [
      {
        key: "n1",
        value: parseFloat(document.getElementById("input1").value),
      },
      {
        key: "n2",
        value: parseFloat(document.getElementById("input2").value),
      },
      {
        key: "n3",
        value: parseFloat(document.getElementById("input3").value),
      },
      {
        key: "n4",
        value: parseFloat(document.getElementById("input4").value),
      },
      {
        key: "n5",
        value: parseFloat(document.getElementById("input5").value),
      },
      {
        key: "n6",
        value: parseFloat(document.getElementById("input6").value),
      },
      {
        key: "n7",
        value: parseFloat(document.getElementById("input7").value),
      },
      {
        key: "n8",
        value: parseFloat(document.getElementById("input8").value),
      },
      {
        key: "n9",
        value: parseFloat(document.getElementById("input9").value),
      },
      {
        key: "n10",
        value: parseFloat(document.getElementById("input10").value),
      },
    ];

    const mean = arr.reduce((s, n) => s   (n.value || 0), 0) / arr.length;
    const variance = arr.reduce((s, n) => s   ((n.value || 0) - mean) ** 2, 0) / (arr.length - 1);
    document.getElementById("s").value = Math.sqrt(variance);
  }
</script>
<input type="number" id="input1" />
<input type="number" id="input2" />
<input type="number" id="input3" />
<input type="number" id="input4" />
<input type="number" id="input5" />
<input type="number" id="input6" />
<input type="number" id="input7" />
<input type="number" id="input8" />
<input type="number" id="input9" />
<input type="number" id="input10" oninput="s10();" placeholder="Type here" />
<input type="text" id="s" placeholder="standardDeviation" />

CodePudding user response:

Okay a couple of small bugs in your code:

When using your arr, you should keep in mind the number is located in arr[item].value, an is not the item itself. You tried counting with objects, which results in NaN.

When calculating the mean, you did not pass in an initial value, which means you started counting with undefined, which gives NaN, which propagates to all your code. So

const mean = arr.reduce((s, n) => s   n) / arr.length;

should be

const mean = arr.reduce((s, n) => s   n.value, 0) / arr.length;

The same rule applies for your average calculation, where arr[item].value is your value, not the item itself.

function s10() {

  var n1 = parseFloat(document.getElementById('input1').value);
  var n2 = parseFloat(document.getElementById('input2').value);
  var n3 = parseFloat(document.getElementById('input3').value);
  var n4 = parseFloat(document.getElementById('input4').value);
  var n5 = parseFloat(document.getElementById('input5').value);
  var n6 = parseFloat(document.getElementById('input6').value);
  var n7 = parseFloat(document.getElementById('input7').value);
  var n8 = parseFloat(document.getElementById('input8').value);
  var n9 = parseFloat(document.getElementById('input9').value);
  var n10 = parseFloat(document.getElementById('input10').value);

  var arr = [{
      key: 'n1',
      value: parseFloat(document.getElementById('input1').value)
  }, {
      key: 'n2',
      value: parseFloat(document.getElementById('input2').value)
  }, {
      key: 'n3',
      value: parseFloat(document.getElementById('input3').value)
  }, {
      key: 'n4',
      value: parseFloat(document.getElementById('input4').value)
  }, {
      key: 'n5',
      value: parseFloat(document.getElementById('input5').value)
  }, {
      key: 'n6',
      value: parseFloat(document.getElementById('input6').value)
  }, {
      key: 'n7',
      value: parseFloat(document.getElementById('input7').value)
  }, {
      key: 'n8',
      value: parseFloat(document.getElementById('input8').value)
  }, {
      key: 'n9',
      value: parseFloat(document.getElementById('input9').value)
  }, {
      key: 'n10',
      value: parseFloat(document.getElementById('input10').value)
  }, ];

  const mean = arr.reduce((s, n) => s   n.value, 0) / arr.length;
  const variance = arr.reduce((s, n) => s   (n.value - mean) ** 2, 0) / (arr.length - 1);
                  
  document.getElementById('s').value = Math.sqrt(variance);
  
}
<input type="text" id="input10" oninput="s10();" />
<input type="number" id="input1" value="1" />
<input type="number" id="input2" value="2" />
<input type="number" id="input3" value="3" />
<input type="number" id="input4" value="4" />
<input type="number" id="input5" value="5" />
<input type="number" id="input6" value="6" />
<input type="number" id="input7" value="7" />
<input type="number" id="input8" value="8" />
<input type="number" id="input9" value="9" />
<input type="number" id="s" placeholder="standardDeviation" />

CodePudding user response:

I am not a JavaScript practionner, but I suggest the following:

  • In case the user inputs only one value then std = 0
  • In case it is more than one value the call to the calculations should be done everywhere for simplicity and real-time calculation.
  • Building the array can be done dynamically for more inputs such that the input id is defined as input{i}.
  • Checking for NaN is mandatory before accepting any value.

So the code could be,

<input type="text" id="input1" oninput="s10();"/>
<input type="text" id="input2" oninput="s10();"/>
<input type="text" id="input3" oninput="s10();"/>
<input type="text" id="input4" oninput="s10();"/>
<input type="text" id="input5" oninput="s10();"/>
<input type="text" id="input6" oninput="s10();"/>
<input type="text" id="input7" oninput="s10();" />
<input type="text" id="input8" oninput="s10();" />
<input type="text" id="input9" oninput="s10();" />
<input type="text" id="input10" oninput="s10();" />
<input type="text" id="s" placeholder="standardDeviation" />
function s10() {
  let arr = [];
  N = 10; // Can be changed to be identified dynamically
  for(i=1; i<=N; i  ) {
    let input_id = "input" String(i);
    let val = parseFloat(document.getElementById(input_id).value);
    if (!isNaN(val)) {
      arr.push(val);
    };
  };
  if (arr.length == 0) {
    document.getElementById('s').value = NaN;
  }
  else if (arr.length == 1) {
    const variance = 0;
    document.getElementById('s').value = Math.sqrt(variance);
  } else {
    const mean = arr.reduce((s, n) => s   n) / arr.length;
    const variance = arr.reduce((s, n) => s   (n - mean) ** 2, 0) / (arr.length - 1);
    document.getElementById('s').value = Math.sqrt(variance);
  };
}
```
  • Related