C# WinsForm,频率分布 Table [更新]

C# WinsForm, Frequency Distribution Table [Updated]

更新01 感谢 Caius,找到了主要问题,“如果”的逻辑是错误的,现在已修复并给出正确的结果。循环仍然在辅助列表上创建比需要更多的位置,主列表上的每个数字都有一个额外的位置。

针对以下问题,我更新了下面的代码以供参考:

-001 我能弄清楚为什么它会创建所需的位置,for 循环应该 运行 只有在 foreach 完成其循环后才正确? -002 为了解决这个问题,我使用了 List.Remove() 来删除所有的 0,到目前为止没有崩溃,但是,事实上我正在创建额外的索引,而不是删除它们,如果我有大量数字列表,是否意味着性能下降?或者是可接受的解决方案?

描述

它应该读取中央 List1 (numberList) 中的所有数字,并计算特定 (0|-15 / 15|-20) 范围内的数字数量,为此我使用另一个列表,每个range 是 List2 (numberSubList) 上的一个位置,其中 List2 上的每个数字表示该范围内存在多少个数字。 -范围随着数字的增减而变化

代码:

void Frequency()
        {

            int minNumb = numberList.Min();
            int maxNumb = numberList.Max();
            int size = numberList.Count();

            numberSubList.Clear();
            dGrdVFrequency.Rows.Clear();
            dGrdVFrequency.Refresh();

            double k = (1 + 3.3 * Math.Log10(size));
            double h = (maxNumb - minNumb) / k;

            lblH.Text = $"H: {Math.Round(h, 2)} / Rounded = {Math.Round(h / 5) * 5}";
            lblK.Text = $"K: {Math.Round(k, 4)}";

            if (h <= 5) { h = 5; }
            else { h = Math.Round(h / 5) * 5; }
            

            int counter = 1;
            for (int i = 0; i < size; i++)
            {
                numberSubList.Add(0); // 001 HERE, creating more positions than needed, each per number.
                foreach (int number in numberList)
                {
                    if (number >= (h * i) + minNumb && number < (h * (i + 1)) + minNumb)
                    {
                        numberSubList[i] = counter++;
                    }
                }
                numberSubList.Remove(0); // 002-This to remove all the extra 0's that are created.
                counter = 1;
            }

            txtBoxSubNum.Clear();
            foreach (int number in numberSubList)
            {
                txtBoxSubNum.AppendText($"{number.ToString()} ,  ");
            }

            lblSubTotalIndex.Text = $"Total in List: {numberSubList.Count()}";
            lblSubSumIndex.Text = $"Sum of List: {numberSubList.Sum()}";

            int inc = 0;
            int sum = 0;
            foreach (int number in numberSubList)
            {
                sum = sum + number;
                int n = dGrdVFrequency.Rows.Add();
                dGrdVFrequency.Rows[n].Cells[0].Value = $"{(h * inc) + minNumb} |- {(h * (1 + inc)) + minNumb}";
                dGrdVFrequency.Rows[n].Cells[1].Value = $"{number}";
                dGrdVFrequency.Rows[n].Cells[2].Value = $"{sum}";
                dGrdVFrequency.Rows[n].Cells[3].Value = $"{(number * 100) / size} %";
                dGrdVFrequency.Rows[n].Cells[4].Value = $"{(sum * 100) / size} %";
                inc++;
            }
        }

显示更新版本的屏幕截图。

我认为,如果您的目标是仅将 17 存储在“15 到 25”插槽中,这就很不靠谱了:

if (number <= (h * i) + minNumb) // Check if number is smaller than the range limit

因为它是在一个循环中找到的,该循环将移动到下一个范围,“25 到 35”,它只询问数字 17 是否小于上限(并且 17 小于 35),所以 17 是也符合25-35的范围

FWIW 数字应该在的范围可以从数字中导出,(number - min) / number_of_ranges - 在您创建例如 10 个范围的那一刻,然后您访问每个数字 10 次以将其放入范围,所以你做的操作比你真正需要的要多 9 倍