9 Replies - 1840 Views - Last Post: 05 October 2010 - 10:08 AM Rate Topic: -----

#1 Dev1462  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 145
  • Joined: 20-May 10

Trouble finding the Median

Posted 03 October 2010 - 06:08 PM

Ok, well my FindMedian() method is having a lot of trouble with its if statment i believe...you see when the sample of numbers i give it is even, it finds the median no problem by simply adding them up and dividing by 2. Now, when i have an odd number of samples, the logic is messed up. for instance, if you enter the numbers 1, 2, 3, 4, 5(without commas) i get 3.5 as the median. Im so lost and confused as to why this is happening. Can you see any logical errors i cant with my noobish eyes? Its a console app, so you can copy+paste to test easily

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

namespace StandardDeviation
{
    class Program
    {
        public static void Main(string[] args)
        {

            string rawData;
            string[] strseperatedData;
            double[] dseperatedData;
            double mean;
            double median;

            Console.WriteLine("\t|///////////////////////////////////|\n");
            Console.WriteLine("\t|/////Joe's Standard Deviation/////|\t\n");
            Console.WriteLine("\t|///////////////////////////////////|\n");
            Console.WriteLine("\tSeperate your numbers with commas");
   
            rawData = Console.ReadLine();
            strseperatedData = rawData.Split(new char[] {' '});
            dseperatedData = new double[strseperatedData.Length];

            for (int i = 0; i < strseperatedData.Length; i++)
            {
                dseperatedData[i] = Convert.ToDouble(strseperatedData[i]);
            }
            Array.Sort(dseperatedData);
            foreach (double dd in dseperatedData)
            {
                Console.Write(dd + ", ");
            }
            Console.WriteLine("\n");
            Program prog = new Program();
            mean = prog.FindMean(dseperatedData);
            median = prog.FindMedian(dseperatedData);

            Console.WriteLine("Mean: " + mean);
            Console.WriteLine("Median: " + median);
            

            Console.ReadLine();
        }
        public double FindMean(double[] newData)
        {
            double themean = 0;
            for (int i = 0; i < newData.Length; i++)
            {
                themean += newData[i];
            }
            themean /= newData.Length;
            return themean;
        }
        /// <summary>
        /// This method here is made to find the Median, it finds the middle value. I then asks if the value is a whole number,
        /// if it is, then it takes the number in that array slot. If it is .5 then it needs to take the position
        /// higher and the one lower...add then together and divide it by 2.
        /// </summary>
        /// <param name="newData"></param>
        /// <returns></returns>
        public double FindMedian(double[] newData)
        {
            //I declare decimal because there is a chance the number is .5
            decimal arrayMiddleIndex = (newData.Length + 1) / 2;

            //The if statment asks, if there IS an odd number of numbers do this
            if (arrayMiddleIndex == Math.Floor(arrayMiddleIndex))
            {
                //If arrayMiddleIndex is a whole number, we convert it to int
                int convertedIndex2 = Convert.ToInt32(arrayMiddleIndex);
                int convertedIndex1 = convertedIndex2 - 1;
                //We assign the values from those 2 slots to two double variables
                double num1 = newData[convertedIndex1];
                double num2 = newData[convertedIndex2];
                Console.WriteLine("Using the numbers: " + num1 + num2 + " to find the median");

                //Then we add up those numbers and divide them by 2
                double medianSum = (num1 + num2) / 2;

                //Returns the number
                return medianSum;
            }
            else
            {
                arrayMiddleIndex = Math.Floor(arrayMiddleIndex);
                int tempNum = Convert.ToInt32(arrayMiddleIndex);
                return newData[tempNum];

            }
        }

    }
}



Is This A Good Question/Topic? 0
  • +

Replies To: Trouble finding the Median

#2 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Trouble finding the Median

Posted 03 October 2010 - 09:04 PM

Ok :)

Several things:

1) this is unnecessary:

...
Program prog = new Program();
mean = prog.FindMean(dseperatedData);
median = prog.FindMedian(dseperatedData);
...



FindMean() and FindMedian() are methods of Class Program and so are directly callable from Main()

Instead:

...
//Program prog = new Program();  delete this line
mean = FindMean(dseperatedData);
median = FindMedian(dseperatedData);
...
// declare the methods static like Main()
public static double FindMean(double[] newData)
...
public static double FindMedian(double[] newData)
...



Next, the median number in a sorted list is defined as: half the numbers in the list will be less, and half the numbers will be greater. If the number of numbers in the list is even then the median value must be calculated as lying between the 'center' two numbers in the list.

But if the list has an odd number of numbers then the median is not calculated. It is the center number. See How to Find the Median Value

So in FindMedian():

...
int arrayMiddleIndex = newData.Length / 2;
int oddSize = newData.Length % 2;
...



If the array is odd sized then arrayMiddleIndex is the index into the array for the median value. If it is even then you calculate the 'missing' value.

This post has been edited by n8wxs: 03 October 2010 - 09:15 PM

Was This Post Helpful? 0
  • +
  • -

#3 lordofduct  Icon User is offline

  • I'm a cheeseburger
  • member icon


Reputation: 2506
  • View blog
  • Posts: 4,615
  • Joined: 24-September 10

Re: Trouble finding the Median

Posted 03 October 2010 - 09:34 PM

[NOTE / EDIT] didn't notice the previous post, I had this page just sitting open for a while while I was playing fallout.




I'd like to first make an observation...

your variable names are complicated. Why such long winded names?

arrayMiddleIndex
dSeperatedData

and some are just not very descriptive... like newArr...

here this seems cleaner:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\t|///////////////////////////////////|");
            Console.WriteLine("\t|/////Joe's Standard Deviation//////|");
            Console.WriteLine("\t|///////////////////////////////////|");
            Console.WriteLine("\tSeperate your numbers with commas");

            string input = Console.ReadLine();
            string[] sarr = input.Split(',');
            double[] values = new double[sarr.Length];

            for (int i = 0; i < sarr.Length; i++)
            {
                values[i] = Convert.ToDouble(sarr[i]);
            }
            Array.Sort(values);
            foreach (double dval in values)
            {
                Console.Write(dval.ToString() + ", ");
            }
            Console.Write("\n");

            double mean = FindMean(values);
            double median = FindMedian(values);

            Console.WriteLine("Mean: " + mean);
            Console.WriteLine("Median: " + median);


            Console.ReadLine();

        }

        static double FindMean(double[] values)
        {
            double mean = 0;
            for (int i = 0; i < values.Length; i++)
            {
                mean += values[i];
            }

            mean /= values.Length;
            return mean;
        }

        /// <summary>
        /// This method here is made to find the Median, it finds the middle value. I then asks if the value is a whole number,
        /// if it is, then it takes the number in that array slot. If it is .5 then it needs to take the position
        /// higher and the one lower...add then together and divide it by 2.
        /// </summary>
        /// <param name="newData"></param>
        /// <returns></returns>
        static double FindMedian(double[] values)
        {
            //I declare decimal because there is a chance the number is .5
            decimal mi = (values.Length + 1) / 2;

            //The if statment asks, if there IS an odd number of numbers do this
            if (mi == Math.Floor(mi))
            {
                //If arrayMiddleIndex is a whole number, we convert it to int
                int i2 = Convert.ToInt32(mi);
                int i1 = i2 - 1;
                //We assign the values from those 2 slots to two double variables
                double num1 = values[i1];
                double num2 = values[i2];
                Console.WriteLine("Using the numbers: " + num1 + num2 + " to find the median");

                //Then we add up those numbers and divide them by 2
                double medianSum = (num1 + num2) / 2;

                //Returns the number
                return medianSum;
            }
            else
            {
                mi = Math.Floor(mi);
                int ti = Convert.ToInt32(mi);
                return values[ti];

            }
        }
    }




now for your problems... well first off...

//I declare decimal because there is a chance the number is .5
decimal mi = (values.Length + 1) / 2;

that's not the middle index... think, if we had an array of length 3, that's indices 0,1,2... middle being 1. But your algorithm there returns 2 [(3 + 1) / 2].

You probably want:

decimal mi = (values.Length - 1) / 2;

further more here you say:

//The if statment asks, if there IS an odd number of numbers do this
if (mi == Math.Floor(mi))

if there's an odd number why would you take the mean of the two middle values? There's only 1 middle value when it's odd. You should be doing this when it's even!

Oh and you may like modulo (the % symbol) it gives you the remainder when one value is divided by the other. Great for finding out this kind of info.

Really though this 'decimal' index thing is kind of overkill. We could just base it off the length.

Here's the rule for median:

1) an empty list has no median
2) an odd number length list's median is the '(length - 1)/2' entry
3) an even number length list's median is the mean of (length / 2) and (length / 2) - 1 entries

So lets fix this all up...


class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("\t|///////////////////////////////////|");
            Console.WriteLine("\t|/////Joe's Standard Deviation//////|");
            Console.WriteLine("\t|///////////////////////////////////|");
            Console.WriteLine("\tSeperate your numbers with commas");

            string input = Console.ReadLine();
            string[] sarr = input.Split(',');
            double[] values = new double[sarr.Length];

            for (int i = 0; i < sarr.Length; i++)
            {
                values[i] = Convert.ToDouble(sarr[i]);
            }
            Array.Sort(values);
            foreach (double dval in values)
            {
                Console.Write(dval.ToString() + ", ");
            }
            Console.Write("\n");

            double mean = FindMean(values);
            double median = FindMedian(values);

            Console.WriteLine("Mean: " + mean);
            Console.WriteLine("Median: " + median);


            Console.ReadLine();

        }

        static double FindMean(double[] values)
        {
            double sum = 0;
            for (int i = 0; i < values.Length; i++)
            {
                sum += values[i];
            }
            return sum / values.Length;
        }

        static double FindMedian(double[] values)
        {
            //return NaN if there are no values
            if (values.Length < 1) return double.NaN;

            //if the remainder of the length when divided by 2, then it's divisible by 2... definition of even
            if (values.Length % 2 == 0)
            {
                //if even number of entries, return the mean of the two middle values
                int hi = values.Length / 2;
                int li = hi - 1;

                return (values[hi] + values[li]) / 2;
            }
            else
            {
                //if odd number of entries, return the middle one
                return values[(values.Length - 1) / 2];
            }
        }
    }


This post has been edited by lordofduct: 04 October 2010 - 06:18 AM

Was This Post Helpful? 1
  • +
  • -

#4 Dev1462  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 145
  • Joined: 20-May 10

Re: Trouble finding the Median

Posted 04 October 2010 - 05:57 AM

genius work with the modulus == 0! however, int li just needs to be (values.length / 2) - 1 then BAM its flawless! thanks a bunch man! time to find the mode using nested looooooops
Was This Post Helpful? 0
  • +
  • -

#5 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4309
  • View blog
  • Posts: 7,463
  • Joined: 08-June 10

Re: Trouble finding the Median

Posted 05 October 2010 - 09:51 AM

In case you're allowed to use LINQ, here's a simplified way to do it. Mode is also quite easy if you understand Group By.

static void Main()
{
    int[] numbers = { 1, 8, 5, 6, 5, 7, 6, 2, 0, 10 };
    Console.WriteLine(FindMedian(numbers));
    Console.WriteLine(FindMode(numbers));
    Console.ReadKey();
}

private static double FindMedian(IEnumerable<int> numbers)
{
    int count = numbers.Count();
    if (count < 1)
        return double.NaN;
    var sorted = numbers.OrderBy(x => x);
    int middle = count / 2;
    if (count % 2 == 0)
        return (sorted.ElementAt(middle) + sorted.ElementAt(middle - 1)) / 2.0;
    else
        return sorted.ElementAt(middle);
}

private static int FindMode(IEnumerable<int> numbers)
{
    if (numbers.Count() < 1)
        return 0;
    else return numbers
        .GroupBy(x => x)
        .OrderByDescending(x => x.Count())
        .FirstOrDefault()
        .Key;
}


Was This Post Helpful? 0
  • +
  • -

#6 Brewer  Icon User is offline

  • Awesome
  • member icon

Reputation: 178
  • View blog
  • Posts: 1,044
  • Joined: 14-June 10

Re: Trouble finding the Median

Posted 05 October 2010 - 09:56 AM

I am pretty sure you could use an array (or the equivalent in C#) to do this. Sort the numbers into the array from least to greatest, and remove one integer from the start of the array, then remove one integer from the end of the array. Continue this until there is only one integer left and that will be your median.
Was This Post Helpful? 0
  • +
  • -

#7 Curtis Rutland  Icon User is online

  • (╯□)╯︵ (~ .o.)~
  • member icon


Reputation: 4309
  • View blog
  • Posts: 7,463
  • Joined: 08-June 10

Re: Trouble finding the Median

Posted 05 October 2010 - 09:59 AM

That way would be incorrect in the case of an even number of values in the array. Also, removing values from the array wouldn't be the most efficient way to go about this.
Was This Post Helpful? 0
  • +
  • -

#8 Brewer  Icon User is offline

  • Awesome
  • member icon

Reputation: 178
  • View blog
  • Posts: 1,044
  • Joined: 14-June 10

Re: Trouble finding the Median

Posted 05 October 2010 - 10:02 AM

How do you get the median of a list of an even amount of numbers?
Was This Post Helpful? 0
  • +
  • -

#9 n8wxs  Icon User is offline

  • --... ...-- -.. . -. ---.. .-- -..- ...
  • member icon

Reputation: 971
  • View blog
  • Posts: 3,878
  • Joined: 07-January 08

Re: Trouble finding the Median

Posted 05 October 2010 - 10:07 AM

View PostJambr, on 05 October 2010 - 09:02 AM, said:

How do you get the median of a list of an even amount of numbers?

http://www.mathsisfun.com/median.html
Was This Post Helpful? 0
  • +
  • -

#10 Brewer  Icon User is offline

  • Awesome
  • member icon

Reputation: 178
  • View blog
  • Posts: 1,044
  • Joined: 14-June 10

Re: Trouble finding the Median

Posted 05 October 2010 - 10:08 AM

That's what I thought, thanks!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1