C中的随机数不是随机的

时间:2015-03-13 19:24:27

标签: c random

这是我的程序的代码。它应该从用户那里获得两个数字,然后使用rand函数生成随机数。 但是当我编译它时,数字不是随机的。

我也在java中写过这个,并且那个完美无缺。

C版:

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

int cmpfunc();

int main()
{
   puts("How many numbers do you want to generate?");
   int n;
   scanf("%d", &n);
   int numbers[n];

   puts("What should be the largest number possible?");
   int m, i;
   scanf("%d", &m);
   int result[m];

   for(i=0;i<m;i++)
       numbers[i] = i + 1;

       srand(time(NULL));
   for(i=0;i<n;i++)
   {
       int r = rand() % m;

       result[i] = numbers[r];
       numbers[r] = numbers[m - 1];
       m--;

   }

   qsort(result, n, sizeof(int), cmpfunc); //sorting the result array

   for(i=0;i<n;i++)
   {
       printf("%d\n", result[i]);
   }

    getch();
    return 0;
}

int cmpfunc (const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b );
}

编辑:srand在循环中,人们说它不应该被多次调用。所以我把它拿出来但是没有帮助。

Java版:

import java.util.*;

public class RandomNumberGenerator {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);

        System.out.println("How many numbers do you want to generate?");
        int n = in.nextInt();

        System.out.println("What should be the largest number possible?");
        int m = in.nextInt();

        int numbers[] = new int[m];
        for(int i=0;i<numbers.length;i++)
            numbers[i] = i + 1;

        int result[] = new int[n];
        for(int i=0;i<result.length;i++)
        {
            // make a random index between 0 and n - 1
            int r = (int) (Math.random() * m );

            result[i] = numbers[r];
            // move the last element into the random location
            numbers[r] = numbers[m - 1];
            m--;
        }

        System.out.println("Do you want the result to be sorted? (1 for Yes, others for No)");
        int ans = in.nextInt();

        if(ans==1)
            Arrays.sort(result);

          System.out.println("Result:");
          for (int r : result)
             System.out.println(r);

          pressAnyKeyToContinue();

    }

    private static void pressAnyKeyToContinue()
     { 
            System.out.println("Press Enter to continue.");
            try
            {
                System.in.read();
            }  
            catch(Exception e)
            {}
     }

}

编辑2:

c输出:(不是随机的,已排序的)

enter image description here

java输出:(随机,排序)

enter image description here

编辑3:

正如我在评论中所说,价值观是: n = 55 m = 9808

我也在使用代码块,因此头文件并不是真正的问题。它们由代码块自动加载。

编辑4:

我对人们的建议印象深刻。 qsort在生成随机数时没有改变。它只是排序数组。所以即使我删除它,它也不会改变任何东西。

在一组随机数中,我们预计任何两个相邻元素之间的差异也是随机的。此属性在排序下保留。我对C和Java中的随机数进行排序可以检查这个属性。如您所见,在C代码中,相邻元素之间的差异都是相同的。这让我相信C代码不是生成随机数,而是Java代码。

编辑5:

并且我确定java和c之间的算法应该没有区别。

编辑6:

对不起,我不是专业人士。我只想尝试制作我所拥有的Java程序的C版本。我们非常感谢固定代码。

****编辑决赛:** 终于搞定了。数组&#34;数字&#34;和&#34;结果&#34;分别存储n和m应该存储m和n。这就是全部。除此之外我改变了他们的名字与人们的建议。有些人告诉我用数组dims切换变量m和n。事实并非如此。 这是任何感兴趣的人的固定代码:**

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

int cmpfunc();

int main()
{
   puts("How many numbers do you want to generate?");
   int  num_numbers;
   scanf("%d", &num_numbers);

   puts("What should be the largest number possible?");
   int num_maximum, i;
   scanf("%d", & num_maximum);


   int numbers[num_maximum];
   int result[num_numbers];

   for(i=0;i<num_maximum;i++) // making
       numbers[i] = i + 1;

       srand(time(NULL)); // seeding rand

   for(i=0;i<num_numbers;i++)
   {
       int r = rand() %  num_maximum; // generates random number between 0 and m-1

       result[i] = numbers[r]; //

       numbers[r] = numbers[ num_maximum - 1];
        num_maximum--;

   }

   puts("Do you want the result to be sorted?");
   int ans;
   scanf("%d", &ans);

   if (ans==1)
   qsort(result,  num_numbers, sizeof(int), cmpfunc); //sorting the result array

   for(i=0;i< num_numbers;i++)
   {
       printf("%d\n", result[i]);
   }

    getch();
    return 0;
}

int cmpfunc (const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b );
}

5 个答案:

答案 0 :(得分:3)

srand(time(NULL));用于种子随机数生成器。它只需要调用一次。你需要将它移出for循环。

如果您每次都播种,那么您最终会得到rand()生成的相同号码。

此外,time()time.h中的原型。

接下来,如 @Blastfurnace 所述,您应该将m而不是n作为qsort()的第二个参数传递。

然后,

for(i=0;i<m;i++)
   numbers[i] = i + 1;

可以()通过为numbers数组生成越界访问来导致UB。

答案 1 :(得分:2)

在您的Java代码中:

int numbers[] = new int[m];
int result[] = new int[n];

在您的C代码中:

int numbers[n];
int result[m];

阵列的大小相反。当我将C代码的定义与Java代码的定义相匹配时,代码似乎有效。

答案 2 :(得分:1)

问题说:

n= 55 m= 9808

但是代码包括:

int numbers[n];

for(i=0;i<m;i++)
   numbers[i] = i + 1;

i通过55后,这是一个缓冲区溢出,导致未定义的行为。

第二个循环有相同的错误(nm交换);另一个错误是将错误的维度传递给qsort


要修复这些错误,请在声明数组的位置后停止在代码中使用mn。而是使用数组的维度。一种方法是写:

#define dimof(ARR) ( sizeof(ARR) / sizeof (ARR)[0] )

然后你可以使用它:

for (int i = 0; i < dimof(numbers); ++i)
    numbers[i] = i + 1;

这样就没有机会混淆哪个变量与哪个数组相关。

你必须为第二个循环和qsort维度做同样的事情。

答案 3 :(得分:0)

因为它比指向每个错误更容易,所以这里将Java代码音译成C,带有一些更有意义的变量名(Horstmann应该知道更好),但是没有排序代码(它正在成为一个分心):

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

int main( void )
{
  int sampleSize, valueRange;
  printf( "How many samples do you want to take: " );
  fflush( stdout );
  scanf( "%d", &sampleSize );

  printf( "What is the range of values, starting from 1: " );
  fflush( stdout );
  scanf( "%d", &valueRange );

  /**
   * The numbers array contains your source values, ranging
   * from 1 to valueRange.  The result array contains a random,
   * non-repeating sample of the numbers array.
   */
  int numbers[valueRange];
  int result[sampleSize];

  for ( int i = 0; i < valueRange; i++ )
    numbers[i] = i + 1;

  srand( time( NULL ));

  for ( int i = 0; i < sampleSize; i++ )
  {
    int sampleIndex = rand() % valueRange;
    result[i] = numbers[sampleIndex];
    numbers[sampleIndex] = numbers[ valueRange - 1 ];
    valueRange--;
  }

  for ( int i = 0; i < sampleSize; i++ )
    printf( "result[%4d] = %d\n", i, result[i] );

  return 0;
}

示例会话:

[fbgo448@n9dvap997]~/prototypes/rand: ./stackrand
How many samples do you want to take: 10
What is the range of values, starting from 1: 10
result[   0] = 5
result[   1] = 6
result[   2] = 7
result[   3] = 4
result[   4] = 10
result[   5] = 3
result[   6] = 2
result[   7] = 8
result[   8] = 1
result[   9] = 9
[fbgo448@n9dvap997]~/prototypes/rand: ./stackrand
How many samples do you want to take: 10
What is the range of values, starting from 1: 10
result[   0] = 9
result[   1] = 3
result[   2] = 7
result[   3] = 1
result[   4] = 4
result[   5] = 8
result[   6] = 2
result[   7] = 5
result[   8] = 6
result[   9] = 10
[fbgo448@n9dvap997]~/prototypes/rand: ./stackrand
How many samples do you want to take: 10
What is the range of values, starting from 1: 100
result[   0] = 28
result[   1] = 90
result[   2] = 100
result[   3] = 4
result[   4] = 15
result[   5] = 76
result[   6] = 3
result[   7] = 60
result[   8] = 65
result[   9] = 21

使用像这样的可变长度数组时要小心;如果为您的范围或样本大小输入足够大的值,则会超出堆栈空间并出现运行时错误。使用malloccalloc分配空间会更安全,但对于小范围和样本大小,这肯定更容易,更轻松。

此外,您应添加一些代码以确保您的样本量始终小于您的值范围。或者Bad Things™会发生。

答案 4 :(得分:-1)

the following code may be what your looking for:

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

int cmpfunc (const void * a, const void * b);

int main()
{
    puts("How many numbers do you want to generate?");
    int n;
    scanf("%d", &n);

    puts("What should be the largest number possible?");
    int m;
    scanf("%d", &m);
    int result[n];

    int i;

    srand(time(NULL));

    for(i=0;i<n;i++)
    {
        result[i] = rand() % m;
    }

    qsort(result, n, sizeof(int), cmpfunc); //sorting the result array

    for(i=0;i<n;i++)
    {
        printf("%d\n", result[i]);
    }

    getchar();
    return 0;
} // end function: main


int cmpfunc (const void * a, const void * b)
{
    return ( *(int*)a - *(int*)b );
} // end function: cmpfunc