【问题标题】:Calculating mode in C — the math is a bit wrongC 中的计算模式——​​数学有点错误
【发布时间】:2013-05-31 17:16:56
【问题描述】:

C 编程的第三天,请多多包涵。我正在做一个初学者练习,我在其中生成随机数并计算平均值、标准差、中位数和众数。

模式中的问题。我将继续从事其他一些项目,但与此同时,我将发布此内容以查看是否有人能发现我的错误。用户在开始时输入随机数的范围和数量。如果最小值为 1,则模式返回正确的值,但如果最小值较大,则不返回。

如果对如何允许多个模式有任何见解也会很有趣 - 我有一个大致的想法(一个额外的 for 循环和一个额外的数组?但不太确定我会怎么做处理仅打印新数组中的相关值)。

这是我的代码(仅相关部分):

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

int main() {

    // setting parameters 
    int SIZE, MIN, MAX;
    printf("How low should the smallest random number be?\n");
    scanf("%d",&MIN);
    printf("How high should the largest random number be?\n");
    scanf("%d",&MAX);
    printf("How many random numbers do you want?\n");
    scanf("%d",&SIZE);

    int rnx[SIZE]; 
    int biggles, *tally, count=0;
    int mode;
    int i,j;
    float mean, sumdev, median;

    tally = (int*) calloc (MAX-MIN,sizeof(int)); // creates an array for the tally in the mode function and initializes it to zero for the incrementing.

    srand(time(NULL)); // random seed outside the loop

  // generate random numbers into an array

  for(i=0;i<SIZE;i++) {
    rnx[i]=round(((double)rand()/(RAND_MAX)*(MAX-MIN)+MIN));
  }

  BubbleSort(rnx,SIZE); //  left out for brevity the actual function I wrote for this but it works

  // calculates the mode

  for(i=MIN;i<MAX;i++) {
      for(j=0;j<SIZE;j++) {
          if(rnx[j]==i) {
              tally[i-MIN]++; // in the second array we register how many times each number occurs in the random sequence, checking from the minimum to maximum.
          }
      }
  }
  mode = biggles;
  // for (j=0;j<10;j++) {
  for(i=MIN;i<MAX;i++) {
      if(tally[i-MIN]>count) {
          count=tally[i-MIN];
          if(count>1) {
              mode=i-MIN+1; }
      }
  } 

  if (mode!=biggles) {
    printf("The mode of the random numbers is %d\n",mode); }
  else { printf("The random numbers have no mode.\n"); } // in case there is no mode. but what if there is more than one?
  free(tally);
  return 0;

}

【问题讨论】:

  • 我注意到的第一件事是biggles 从未初始化,因此当您执行mode = biggles; 时,您将mode 设置为一个完全随机的值。 (另外,biggles 不是描述性或有意义的名称。)
  • 缩进也需要修复。此外,“无模式”意味着一个空列表。这可能不是检查它的最佳方法。如果您至少有一个号码,那么您至少有一个模式。
  • @Patashu 'indeterminate' 将是比“完全随机”更好的词选择。

标签: c mode


【解决方案1】:

当你这样做时:

tally = (int*) calloc (MAX-MIN,sizeof(int));

假设 MAX 为 4,MIN 为 1。这意味着您可以获得 1、2、3 和 4 作为随机数。但是 MAX - MIN = 3,所以您只为 3 分配空间。将其更改为 MAX-MIN+1。

下一个问题是这一行。

round(((double)rand()/(RAND_MAX)*(MAX-MIN)+MIN));

再次说 MAX 为 4,MIN 为 1。这将正确生成从 1 (round(0*(4-1)+1)) 到 4 (round(1*(4-1)+1)) 的值。但是,1 到 1.5 会变成 1,而 1.5 到 2.5 会变成 2,同样只有 3.5 到 4 会变成 4。所以 1 和 4 的可能性是其他数字的一半。

要解决这个问题,试试这个

floor(((double)rand()/(RAND_MAX+1)*(1+MAX-MIN)+MIN));

这仍然是从 1 到 4 的范围,但会为所有可能性提供平等的机会。 (RAND_MAX+1部分是为了确保它不会以非常小的概率生成5)

这就是我计算模式的方式(未经测试):

for (i = 0; i < SIZE; ++i)
{
    tally[rnx[i]-MIN] += 1;
}

int modecount = 0;
int mode = -1;
for (i = 0; i <= MAX-MIN; ++i) //<= instead of < because MAX is inclusive, not exclusive
{
    if (tally[i] > modecount)
    {
        mode = i+MIN;
        modecount = tally[i];
    }
}

在伪代码中:

1) 创建数组 tally,计算每个索引中有多少个随机数。

2) 在计数中查找最大的条目并记下它的位置和计数。

然后,处理多种模式:

在您完全通过tally 并找到该模式后,请扫描tally 以查找与您为您的模式找到的最高计数相同的每个条目。所有这些都是模式,如果您不想分配另一个数组来存储它们,您可以在找到它们时将它们打印出来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-09
    • 2017-02-08
    • 1970-01-01
    • 2015-07-17
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多