Hello, I'm writing an application that computes the variance and average from a list of integers. Here is the assignment info:
Create a function that accepts a list of integers and computes the average and variance of the list.
The variance is computed using the following formula.
The list of integers is passed as a params array.
The function returns the variance as a double.
The average is passed back to the calling function as a reference to type double.
Test the function you created by calling it with a list of integer values. Output the variance and average computed by the function to the screen. This should be done in your Main code, not the function itself.
You may call the function using literal values. This means you do not need to read values in from the keyboard. I demonstrate doing this in my ParamArray video.
Inside your function you may use the array.Sum() and array.Average() methods.
(Worth 25 points) Now overload the function created in part 1 so that it accepts a list of double values. This can be added to the console application created in part 1. Test the function by calling it with a list of values of type double. Output the computed average and variance to the screen.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Assignment_2_ITM_225
{
    class Program
    {
        static double Average(List<int> listvalues)
        {
            double variance = 0;
            foreach (int value in listvalues)
            {
                variance += (intList[i] - Average) * (intList[i] - Average);
            }
            return (double)variance / listvalues.Count;
        }
        static void Main(string[] args)
        {

            List<int> intList = new List<int>();
            string mystring = "";
            do
            {
                Console.Write("Enter an integer (exit to finish): ");
                mystring = Console.ReadLine();
                if (mystring.ToLower() != "exit")
                {
                    intList.Add(int.Parse(mystring));
                }
                else
                {
                    break;
                }
            }
            while (true);
            Console.WriteLine();
            for (int i = 0; i < intList.Count; i++)
            {
                Console.WriteLine("Value {0}: {1}", i + 1, intList[i]);
            }
            Console.WriteLine("\nAverage: {0}\nVariance: {1}", Average(intList), intList.Sum());
            Console.ReadKey();
        }
    }
}

I'm not sure how to get the variance to use the intList[i] for the numbers it needs, how do I do that? And are there any other problems? Thanks!

From Wikipedia's article on variance:

The variance of a random variable or distribution is the expectation, or mean, of the squared deviation of that variable from its expected value or mean.

So you need the mean first; you're already calculating that in Average. So for each original number, find its difference from the mean, square that, and remember it... then average all of the resulting values.

The calculation should look very similar, and you should in fact be able to reuse Average to get the final result.

Does that make sense? If not, there is a basic example in the Wikipedia article that may help

I know the equation for variance, I just don't know how to reference the values in the main part of the program to this part: static double Average(List<int> listvalues)

Ah, ok. You'll want to store the result of calling Average(intList) in a double variable--here, a local variable in Main would work just fine.

Have another look at your Average method... it's not really calculating an average, is it?

static double Average(List<int> listvalues)
{
    double variance = 0;
    foreach (int value in listvalues)
    {
        variance += (intList[i] - Average) * (intList[i] - Average);
    }
    return (double)variance / listvalues.Count;
}

You're trying to calculate variance there, which is getting a little ahead of itself.

First thing you should do is write a method that just does a simple average--you need that value to calculate variance. Then you should end up with something like this in a Variance method:

double average = Average(intList);
// Build a new list of (intList[i] - average)^2
return Average(newList);

Edited 3 Years Ago by gusano79

So after my teacher helped me a little I changed the program around to this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Assign_4
{
    static double MeanVar(ref double mean, params int[] intValues)
        {
            mean = intValues.Average();
            double variance = 0;
            for(int i=0; i < intValues.Length; i++)
            {
                variance += Math.Pow((intValues[i] - mean), 2);
            }
            return variance / (intValues.Length - 1);
    class Program
    {

      static void Main(string[] args) 
        {

        double myAverage = 0;
        double variance = MeanVar(ref myAverage, 1,5,7,9,11);
        Console.WriteLine("Average is " + myAverage); 
        Console.WriteLine("Variance is " + variance);
        Console.ReadKey();
        }
    }

It's not working yet, do I need to make an array or list in main, or what? Not quite sure.

You have a method outside your class and it doesn't have a closing bracket. Fix those two issues and you should be okay.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Assign_4
{
    static double MeanVar(ref double mean, params int[] intValues)
        {
            mean = intValues.Average();
            double variance = 0;
            for(int i=0; i < intValues.Length; i++)
            {
                variance += Math.Pow((intValues[i] - mean), 2);
            }
            return variance / (intValues.Length - 1);
        }
    class Program
    {

      static void Main(string[] args) 
        {

        double myAverage = 0;
        double variance = MeanVar(ref myAverage, 1,5,7,9,11);
        Console.WriteLine("Average is " + myAverage); 
        Console.WriteLine("Variance is " + variance);
        Console.ReadKey();
        }
    }
}

Okay, now the double before MeanVar, the params int [], the return, the intValues, and the closing bracket are all having errors.

And thank you all for your help. :) I really apprectiate it, I think I might be getting a little more used to C#, but I still don't fully understand it.

Try this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace Assign_4
    {

        class Program
        {
            static double MeanVar(ref double mean, params int[] intValues)
            {
                mean = intValues.Average();
                double variance = 0;
                for (int i = 0; i < intValues.Length; i++)
                {
                    variance += Math.Pow((intValues[i] - mean), 2);
                }
                return variance / (intValues.Length - 1);
            }            
            static void Main(string[] args)
            {
                double myAverage = 0;
                double variance = MeanVar(ref myAverage, 1,5,7,9,11);
                Console.WriteLine("Average is " + myAverage);
                Console.WriteLine("Variance is " + variance);
                Console.ReadKey();
            }
        }
    }

Works perfectly, thank you very much. :) Do you know how to overload the function to allow it to accept doubles as the input?

All the articles/problems I find online aren't relevant, I can't figure it out.

try this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace Assign_4
    {
        class Program
        {
            static double MeanVar(ref double mean, object[] objValues)
            {
                List<double> Values = new List<double>();
                foreach (object Value in objValues)
                {
                    double TempValue = 0;
                    bool GoodParse = double.TryParse(Value.ToString(), out TempValue);
                    if (GoodParse)
                    {
                        Values.Add(TempValue);
                    }
                }
                mean = Values.Average();
                double variance = 0;
                for (int i = 0; i < Values.Count; i++)
                {
                    variance += Math.Pow((Values[i] - mean), 2);
                }
                return variance / (Values.Count - 1);
            }            
            static void Main(string[] args)
            {
                double myAverage = 0;
                //object[] Values = {1,5,7,9,11};
                //object[] Values = { 1.5, 5.8, 7.2, 9.3, 11.9 };
                object[] Values = { "1.5", "5.8", "a",7.2, 9.3, 11.9 }; 
                double variance = MeanVar(ref myAverage, Values);
                Console.WriteLine("Average is " + myAverage);
                Console.WriteLine("Variance is " + variance);
                Console.ReadKey();
            }
        }
    }

With this code you can basically put any value into 'Values', and anything that isn't a number will be ignored. I left my test lines in there so you can see for yourself.

That's not really an overload though is it. Actually that code should be nuked from orbit...

You allow an object type and then enforce the double type? Ick >.< Not only is it more complex than necessary, but also confusing to any consumer. The method you posted also has unexpected side effects, where any value you pass that cannot be converted to double is lost and dropped from the calculation.

If you have somewhere in your app where it is possible to pass multiple object types to a single method, I would seriously rethink your design because something is wrong :P

If you're going to allow things like "passing any object to it" then at least use Generics so that the method becomes strongly typed.

To answer the OP's question about overloads though; they are methods that have the same name but accept different parameters.

void MyMethod(String argument) and void MyMethod(Int32 argument) are overloads of MyMethod

So simply add another method along with the one that accepts integers, only change the integer parameter to double on the new one.

The method you posted also has unexpected side effects, where any value you pass that cannot be converted to double is lost and dropped from the calculation.

That was the intention, if it's not a numeric value then it can't be calculated.

It's just one way not necessarily the best way, gave the OP something to work with, since after almost a whole day no one else has anything but destructive criticism and vague suggestions.

Edited 3 Years Ago by tinstaafl

I just figured out how to do that:

So simply add another method along with the one that accepts integers, only change the integer parameter to double on the new one.

Thanks though! Thank you guys. I now have to make this console application with the same abilities into a windows form, so I may have more questions, haha. I really appreciate all of your help.

This question has already been answered. Start a new discussion instead.