C 语言中随机数的生成

本文探讨如何在C语言中生成n个不重复的随机数,并提供了检查序列有序性和是否存在重复元素的方法,包括使用排序和C++ STL中的set结构。同时介绍了 rand() 和 set.insert() 的用法,以及编程珠玑中的相关理念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 产生n个不重复的随机数字,范围是[0, n)。基本思想:有序数据的随机交换。

static int randint(int l, int u)
{	return l + rand() % (u-l+1);
}

/* generate n distinct random integer in range [0, n) 
 * the implementation depends on a global varible 
 *     int gRawDataSet[DATA_SET_SIZE];
 * 
 * generate random index then replace the current element
 * with that one.
 */
static void gen_distinct_random(int n)
{
	//printf("%d\n", n);
	int i;
	for (i = 0; i < n; i++)
	{
		gRawDataSet[i] = i;
	}
	for (i = 0; i < n; i++)
	{
		int idx = randint(i, n - 1); //printf("idx = %d \n", idx);
		int t = gRawDataSet[idx];
		gRawDataSet[idx] = gRawDataSet[i];
		gRawDataSet[i] = t;
		printf("%d ", gRawDataSet[i]);
	}
	printf("\n");
}

2.检验产生的随机数字序列是否有序? 是否存在重复元素?序列是否有序的判断是一个十分直观的问题,是否存在重复元素的判断就要复杂一些了。可以采用的方法有两类。第一类是采用先排序将重复元素集中再进行检测的方式。第二类是借助额外的数据结构C++ STL中的set就是一个很好的结构,短短的几行代码就能够实现功能。

int sorted(int n)
{
	int i;
	for (i = 0; i < n - 1; i++)
	{
		if (gRawDataSet[i] > gRawDataSet[i + 1]) return 0;
	}
	return 1;
}

/* take advantage of C++ STL set.insert() to check the duplicate
 * reference location:
 * http://www.cplusplus.com/reference/set/set/insert/
 * 
 */
int duplicated(int n)
{
	set<int> s;
	pair<set<int>::iterator, bool> ret;
	int i; 
	for (i = 0; i < n; i++)
	{
		ret = s.insert(gRawDataSet[i]);
		if (ret.second == false) return 1; // the duplicate exist!
	}
	return 0;
}

3.从[0, n)的n个元素的有序序列中随机选取m个有序的元素构成一个新的序列。要求保证每个元素被选中的概率是相等的。

/* generate m distinct sorted random number in [0, n) 
 * rand(): Returns a pseudo-random integral number in the range  0 to RAND_MAX
 * This number is generated by an algorithm that returns a sequence of 
 * apparently non-related numbers each time it is called. 
 * This algorithm uses a seed to generate the series, which should be initialized 
 * to some distinctive value using function srand.
 * http://www.cplusplus.com/reference/cstdlib/rand/?kw=rand  for details.
 * 
 * prototype : double difftime (time_t end, time_t beginning); 
 * Calculates the difference in seconds between beginning and end.
 * this is an inexact method to meter the performance!
 */
void gen_sorted_randint(int n, int m)
{
	int i, j;
	LOG_I("+[ %s ]\n", __FUNCTION__);
	
	#ifdef PERFORMANCE_METER
	time_t tm1, tm2;
	time(&tm1); /* get current time */
	#endif
	j = 0;
	//srand(time(NULL)); /* initialize random seed */
	for (i = 0; i < n; i++)
	{			
		if (rand() % (n - i) < m)
		{	
			gRawDataSet[gDataSetCount++] = i; 			 
			m--;
			printf("%4u ", i);
			if (++j % 8 == 0) printf("\n");
		}
	}
	printf("\n");
	
	#ifdef PERFORMANCE_METER
	time(&tm2);
	double seconds = difftime(tm2, tm1); /* return double */
	LOG_D("[Run time] %.lf s!\n", seconds);
	#endif
	
	LOG_I("-[ %s ]\n", __FUNCTION__);
}
基本思想:按照有序地方式逐个遍历每个元素, 采用随机的方式确定该元素是否加入到新的序列中去。上面的代码中关键部分只有3行。



参考资料

rand()接口的相关介绍  http://www.cplusplus.com/reference/cstdlib/rand/?kw=rand点击打开链接

set.insert()相关介绍 http://www.cplusplus.com/reference/set/set/insert/点击打开链接

programming pearls http://netlib.bell-labs.com/cm/cs/pearls/index.html点击打开链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值