2

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;

}
4

1 回答 1

3

When you do this:

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

Say MAX is 4, MIN is 1. That means you can get 1, 2, 3 and 4 as random numbers. But MAX - MIN = 3, so you allocate space for only 3. Change this to MAX-MIN+1.

The next problem is this line.

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

Again say MAX is 4, MIN is 1. This will produce values anywhere from 1 (round(0*(4-1)+1)) to 4 (round(1*(4-1)+1)) correctly. However, 1 to 1.5 will become 1, whereas 1.5 to 2.5 will become 2, similarly only 3.5 to 4 will become 4. So 1 and 4 are half as likely as other numbers.

To solve this, try this instead

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

This will range from 1 to 4 still but give all possibilities equal opportunity. (The RAND_MAX+1 part is to make sure it doesn't generate a 5 with very tiny probability)

This is how I would calculate mode (untested):

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];
    }
}

In pseudocode:

1) Create the array, tally, with the count of how many random numbers were that number in each index.

2) Look for the largest entry in tally and note its position and count.

Then, to handle multiple modes:

Once you have gone through tally entirely and found the mode, scan tally looking for every entry with the same count as the highest count that you found for your mode. All of those will be modes, you can print them out as you find them if you don't want to allocate another array to store them.

于 2013-05-31T08:57:58.523 回答