I am trying to write a generic class with at type parameter T, and add a method that takes an ArrayList of type T and returns a standard deviation as type double. My program is compiling with no errors, however the standard deviation is incorrect. It is outputting the standard deviation as 2.8722813232690143, when it should be 3.0276503540974917. I cannot seem to find what I am doing wrong. Any help would be greatly appreciated!

import java.util.ArrayList;

public class MyMathClass<T extends Number> {
    public ArrayList<T> myArray;




    public static void main(String[] args) {
        MyMathClass<Integer> intMath = new MyMathClass<>();
      intMath.myArray = new ArrayList<>(10);

            for (int i = 0; i < 10; i++) {
            intMath.myArray.add(1);
         intMath.myArray.add(2);
         intMath.myArray.add(3);
         intMath.myArray.add(4);
         intMath.myArray.add(5);
         intMath.myArray.add(6);
         intMath.myArray.add(7);
         intMath.myArray.add(8);
         intMath.myArray.add(9);
         intMath.myArray.add(10);

            }

        System.out.printf("standard deviation 0-9 "+ stdev(intMath.myArray));
    }

   public static <T extends Number> double stdev(ArrayList<T> a) {
        double average = 0;
      double stdev = 0;

        for (T t : a)
         {

            average = (average + t.doubleValue());
         }
         average = (average / a.size());
         for(T t : a)
         {
         stdev = (stdev + Math.pow((t.doubleValue() - average), 2));
         }
         stdev = (stdev / a.size());
         stdev = Math.pow(stdev, .5);
         return stdev;

            }



}

That is my issue. The answer should be 3.0276503540974917. NOT 2.8722813232690143.
And I can't seem to figure out why.

What you are calculating is the population standard deviation which, for 1-10, is 2.87228. The sample standard deviation for 1-10 is indeed 3.02765. For a sample deviation you need to divide by N - 1 instead of N. I'll leave it up to you to implement that. (hint: N is the length of your list of arguments)

A few general pointers about your code:

      intMath.myArray = new ArrayList<>(10);
            for (int i = 0; i < 10; i++) {
            intMath.myArray.add(1);
         intMath.myArray.add(2);
         intMath.myArray.add(3);
         intMath.myArray.add(4);
         intMath.myArray.add(5);
         intMath.myArray.add(6);
         intMath.myArray.add(7);
         intMath.myArray.add(8);
         intMath.myArray.add(9);
         intMath.myArray.add(10);
            }

That means you're adding 1-10 ten times, i.e. 100 numbers. You have access to the i variable, so use it to populate the ten numbers correctly. One way or another it will mess up your calculations (i.e. when you implement N-1). You need to change it so there's only one intMath.myArray.add left in the loop.

Always program to an interface and encapsulate your variables. So public ArrayList<T> myArray; should be private List<T> myArray;

There is no need for stdev to be static, especially since you already define an instance on line 10. So instead use intMath.stdev(intMath.myArray) on line 27 and remove the static keyword; you should also use List here, and optionally final.

public <T extends Number> double stdev(final List<T> a) 

Lastly, you're using stdev = Math.pow(stdev, .5); to calculate the square root. However, java.lang.Math has a sqrt method just for that:

stdev = Math.sqrt(stdev); 

Edit: keep in mind that you hardcoded 1-10 but by correctly implementing the loop as is you will be calculating 0-9.

commented: Thank you! +0
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.