Calculate Calculate Mean, Median, and Mode (average calculations) in C#.
// ============================================================================
// Source: https://github.com/lukewickstead/DOT-NET-on-Linux/tree/master/SimpleIntroductions/Day2NUnitExample
// ============================================================================
//-----------------------------------------------------------------------
// <copyright file="Mean.cs" >Copyright (c) ThereBNone </copyright>
// <author>Luke Wickstead</author>
namespace MathsLibrary.Average
{
using System;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Mean calcuation
/// </summary>
public class Mean
{
/// <summary>
/// Calculate the specified meandata.
/// </summary>
/// <param name='data'>
/// Data to have the mean calculated
/// </param>
/// <returns>Mean value</returns>
public static decimal Calculate(List<decimal> data)
{
if (data == null)
{
throw new ArgumentNullException();
}
if (data.Count == 0)
{
throw new ArgumentException("No data provided");
}
return data.Sum() / data.Count;
}
}
}
//-----------------------------------------------------------------------
// <copyright file="Median.cs" >Copyright (c) ThereBNone </copyright>
// <author>Luke Wickstead</author>
namespace MathsLibrary.Average
{
using System;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Median calculator
/// </summary>
public class Median
{
/// <summary>
/// Calculate the specified data.
/// </summary>
/// <param name='data'>
/// Data to be averaged
/// </param>
/// <returns>Median data</returns>
public static decimal Calculate(List<decimal> data)
{
if (data == null)
{
throw new ArgumentNullException();
}
if (data.Count == 0)
{
throw new ArgumentException("No data provided");
}
data.Sort();
if (IsEven(data.Count))
{
return CalculatWithEvenData(data);
}
else
{
return CalculatWithOddData(data);
}
}
/// <summary>
/// Calculats the median the with odd data elements.
/// </summary>
/// <returns>
/// The with odd data.
/// </returns>
/// <param name='data'>
/// Data to be averaged
/// </param>
/// <returns>Median data</returns>
private static decimal CalculatWithOddData(List<decimal> data)
{
var middlePosition = (decimal)data.Count / 2;
--middlePosition;
return data[(int)Math.Ceiling((decimal)middlePosition)];
}
/// <summary>Calculats the with even data.</summary>
/// <returns>The with even data.</returns>
/// <param name='data'>Data to be averaged</param>
/// <returns>averaged data</returns>
private static decimal CalculatWithEvenData(List<decimal> data)
{
var middlePosition = data.Count / 2;
--middlePosition;
var lower = data[middlePosition];
var upper = data[middlePosition + 1];
return (lower + upper) / 2;
}
/// <summary>Is the int even</summary>
/// <returns>True/False is the count is event.</returns>
/// <param name='count'>Element being analysed</param>
private static bool IsEven(int count)
{
decimal divCheck = (decimal)count / 2;
return (divCheck - Math.Floor(divCheck)) == 0;
}
}
}
//-----------------------------------------------------------------------
// <copyright file="Mode.cs" >Copyright (c) ThereBNone </copyright>
// <author>Luke Wickstead</author>
namespace MathsLibrary.Average
{
using System;
using System.Collections.Generic;
using System.Linq;
/// <summary>
/// Mode Average
/// </summary>
public class Mode
{
/// <summary>
/// Calculate the mode average
/// </summary>
/// <param name='data'>
/// Data to be averages
/// </param>
/// <returns>Mode average</returns>
public static decimal Calculate(List<decimal> data)
{
if (data == null)
{
throw new ArgumentNullException();
}
if (data.Count == 0)
{
throw new ArgumentException("No data provided");
}
var occuranceCount = CountOccurances(data);
var maxOccurance = occuranceCount.Max(x => x.Value);
var valueWithMaxOccurance = occuranceCount.Where(x => x.Value == maxOccurance).Select(x => x.Key);
if (valueWithMaxOccurance.ToList().Count > 1)
{
throw new NotImplementedException("We have not quite got around to Mode with grouping...");
}
return valueWithMaxOccurance.First();
}
/// <summary>
/// Counts the occurances.
/// </summary>
/// <returns>
/// Dictionary of element vs occurance count
/// </returns>
/// <param name='data'>
/// Data being analysed
/// </param>
/// <returns>Dictionary of occurances of elements</returns>
private static Dictionary<decimal, int> CountOccurances(List<decimal> data)
{
var counter = new Dictionary<decimal, int>();
foreach (decimal value in data)
{
if (counter.ContainsKey(value))
{
counter[value] += 1;
}
else
{
counter[value] = 1;
}
}
return counter;
}
}
}
// --------------------------------------------------------------------------
// Unit tests
// --------------------------------------------------------------------------
//-----------------------------------------------------------------------
// <copyright file="MeanTests.cs" >Copyright (c) ThereBNone </copyright>
// <author>Luke Wickstead</author>
namespace MathsLibrary.Tests
{
using System;
using System.Collections.Generic;
using MathsLibrary.Average;
using NUnit.Framework;
/// <summary>
/// Mean tests.
/// </summary>
[TestFixture]
public class MeanTests
{
/// <summary>
/// Mean test
/// </summary>
[Test]
public void CanCalculateMean()
{
var data = new List<decimal> { 1.1m, 2.2m, 3.3m, 4.4m, 5.5m };
var modeValue = Mean.Calculate(data);
Assert.AreEqual(modeValue, 3.3);
}
/// <summary>
/// Checks error thrown when null passed in
/// </summary>
[Test]
public void WillThrowArgumentNullExceptionWhenNull()
{
Assert.Throws<ArgumentNullException>(() => Mean.Calculate(null));
}
/// <summary>
/// Checks error thrown when an empty collection is passed in.
/// </summary>
[Test]
public void WillThrowArgumentExceptionWhenEmptyCollection()
{
Assert.Throws<ArgumentException>(() => Mean.Calculate(new List<decimal>()));
}
}
}
//-----------------------------------------------------------------------
// <copyright file="MedianTests.cs" >Copyright (c) ThereBNone </copyright>
// <author>Luke Wickstead</author>
namespace MathsLibrary.Tests
{
using System;
using System.Collections.Generic;
using MathsLibrary.Average;
using NUnit.Framework;
/// <summary>
/// Median tests.
/// </summary>
[TestFixture]
public class MedianTests
{
/// <summary>
/// Determines whether this instance can calculate median with odd number.
/// </summary>
[Test]
public void CanCalculateMedianWithOddNumber()
{
var data = new List<decimal> { 1.1m, 2.2m, 3.3m, 4.4m, 5.5m };
var medianVale = Median.Calculate(data);
Assert.AreEqual(medianVale, 3.3);
}
/// <summary>
/// Determines whether this instance can calculate median with even number.
/// </summary>
[Test]
public void CanCalculateMedianWithEvenNumber()
{
var data = new List<decimal> { 1.1m, 2.2m, 3.3m, 4.4m };
var medianVale = Median.Calculate(data);
Assert.AreEqual(medianVale, 2.75);
}
/// <summary>
/// Wills the throw argument null exception when null.
/// </summary>
[Test]
public void WillThrowArgumentNullExceptionWhenNull()
{
Assert.Throws<ArgumentNullException>(() => Median.Calculate(null));
}
/// <summary>
/// Wills the throw argument exception when empty collection.
/// </summary>
[Test]
public void WillThrowArgumentExceptionWhenEmptyCollection()
{
Assert.Throws<ArgumentException>(() => Median.Calculate(new List<decimal>()));
}
}
}
//-----------------------------------------------------------------------
// <copyright file="ModeTests.cs" >Copyright (c) ThereBNone </copyright>
// <author>Luke Wickstead</author>
namespace MathsLibrary.Tests
{
using System;
using System.Collections.Generic;
using MathsLibrary.Average;
using NUnit.Framework;
/// <summary>
/// Mode tests.
/// </summary>
[TestFixture]
public class ModeTests
{
/// <summary>
/// Determines whether this instance can calculate mode with no grouping.
/// </summary>
[Test]
public void CanCalculateModeWithNoGrouping()
{
var data = new List<decimal> { 1.1m, 2.2m, 2.2m, 3.3m, 4.4m, 5.5m };
var modeValue = Mode.Calculate(data);
Assert.AreEqual(modeValue, 2.2);
}
/// <summary>
/// Determines whether this instance can not calculate modewith grouping.
/// </summary>
[Test]
public void CanNotCalculateModewithGrouping()
{
var data = new List<decimal> { 1.1m, 2.2m };
Assert.Throws<NotImplementedException>(() => Mode.Calculate(data));
}
/// <summary>
/// Wills the throw argument null exception when null.
/// </summary>
[Test]
public void WillThrowArgumentNullExceptionWhenNull()
{
Assert.Throws<ArgumentNullException>(() => Mode.Calculate(null));
}
/// <summary>
/// Wills the throw argument exception when empty collection.
/// </summary>
[Test]
public void WillThrowArgumentExceptionWhenEmptyCollection()
{
Assert.Throws<ArgumentException>(() => Mode.Calculate(new List<decimal>()));
}
}
}