C#如何实现从任意数量数值中计算median中位数与mode众数
代码调整方案
1 修复数组长度异常缺陷
原代码中数组固定长度为100,当用户输入的元素数量n小于100时,数组未赋值位置会默认填充0,直接参与统计会导致结果错误,需要调整数组初始化逻辑:将数组初始化操作移动到读取到n之后,修改为对应长度:
// 原代码删除int[] a = new int[100]; Console.Write("Input the number of elements to store in the array :"); n = Convert.ToInt32(Console.ReadLine()); int[] a = new int[n]; // 在此处初始化指定长度的数组
2 中位数扩展方法调用
你提供的GetMedian是int数组的扩展方法,可以直接通过数组实例调用,注意Extensions静态类需要和主程序类放在同一个命名空间下,否则需要提前引用对应命名空间。
另外原扩展方法存在两处可优化点:
- 直接操作原数组引用,排序后会修改原数组的元素顺序,如果需要保留输入顺序,可以修改扩展方法里的临时数组初始化逻辑
- 偶数长度数组计算中位数时,直接对整数做除法会丢失小数精度,需要先转成decimal再做除法
优化后的中位数方法如下:
public static decimal GetMedian(this int[] array) { // 克隆新数组避免修改原数组 int[] tempArray = (int[])array.Clone(); int count = tempArray.Length; Array.Sort(tempArray); decimal medianValue = 0; if (count % 2 == 0) { int middleElement1 = tempArray[(count / 2) - 1]; int middleElement2 = tempArray[(count / 2)]; // 转decimal再做除法避免精度丢失 medianValue = (decimal)(middleElement1 + middleElement2) / 2; } else { medianValue = tempArray[(count / 2)]; } return medianValue; }
3 众数计算实现
众数为数组中出现次数最高的数值,可能存在多个众数,你可以将如下方法加入Extensions静态类中直接调用:
public static List<int> GetMode(this int[] array) { // 按数值分组统计出现次数 var countGroup = array.GroupBy(x => x); // 获取最高出现次数 int maxOccurCount = countGroup.Max(g => g.Count()); // 返回所有达到最高出现次数的数值(即所有众数) return countGroup.Where(g => g.Count() == maxOccurCount).Select(g => g.Key).ToList(); }
4 补充统计结果输出逻辑
在原Main方法的末尾追加如下代码,输出中位数与众数计算结果:
// 输出中位数 decimal median = a.GetMedian(); Console.Write("\n\n中位数为:{0}", median); // 输出众数 List<int> modes = a.GetMode(); Console.Write("\n众数为:"); foreach (var mode in modes) { Console.Write("{0} ", mode); }
完整可运行代码示例
using System; using System.Collections.Generic; using System.Linq; public class Program { public static void Main() { int i, n; Console.Write("\n\nRead n number of values in an array and display it in reverse order:\n"); Console.Write("------------------------------------------------------------------------\n"); Console.Write("Input the number of elements to store in the array :"); n = Convert.ToInt32(Console.ReadLine()); int[] a = new int[n]; Console.Write("Input {0} number of elements in the array :\n", n); for (i = 0; i < n; i++) { Console.Write("element - {0} : ", i); a[i] = Convert.ToInt32(Console.ReadLine()); } Console.Write("\nThe values store into the array are : \n"); for (i = 0; i < n; i++) { Console.Write("{0} ", a[i]); } // 输出统计结果 decimal median = a.GetMedian(); Console.Write("\n\n中位数为:{0}", median); List<int> modes = a.GetMode(); Console.Write("\n众数为:"); foreach (var mode in modes) { Console.Write("{0} ", mode); } } } public static class Extensions { public static decimal GetMedian(this int[] array) { int[] tempArray = (int[])array.Clone(); int count = tempArray.Length; Array.Sort(tempArray); decimal medianValue = 0; if (count % 2 == 0) { int middleElement1 = tempArray[(count / 2) - 1]; int middleElement2 = tempArray[(count / 2)]; medianValue = (decimal)(middleElement1 + middleElement2) / 2; } else { medianValue = tempArray[(count / 2)]; } return medianValue; } public static List<int> GetMode(this int[] array) { var countGroup = array.GroupBy(x => x); int maxOccurCount = countGroup.Max(g => g.Count()); return countGroup.Where(g => g.Count() == maxOccurCount).Select(g => g.Key).ToList(); } }
内容的提问来源于stack exchange,提问作者Javier Rafael
相关产品推荐
相关产品推荐

