使用randn实现randm的通用方法

使用randn实现randm的通用方法

分以下两种情况:

一、n > m

对于n > m的情况,可以直接截断,即不断使用randn生成随机数,直到该随机数小于等于m的倍数为止(该倍数要小于等于n)。

比如rand5实现rand2,因为rand5生成的随机数范围为{1,2,3,4,5},如果随机到了5,那就重新生成,直至为1或2或3或4为止,然后模2,并加1 ,即可得到1或2,且生成1 2 的概率都相同,实现了rand2

#include <cstdio>
#include <cstdlib>
#include <ctime>
using namespace std;

int rand5() {
	return rand() % 5 + 1;
}

int rand2() {
	int res;
	do{
		res = rand5();
	} while(res > 4);
	return res % 2 + 1;
}


int main() {
	srand(time(0)); // 设置随机种子,使随机结果不固定
	printf("rand5的随机结果:\n");
	for (int i = 0; i < 10; i++) {
		printf("%d ", rand5());
	}
	
	printf("\n\nrand2的随机结果:\n");
	for(int i = 0; i < 10; i++) {
		printf("%d ", rand2());
	} 
	return 0;
}

rand5实现rand2

二、 n < m

考虑以下两种情形:

1. rand5生成rand7

rand5的范围比rand7小,无法使用前面直接截断的方法。

考虑到:

rand5的取值范围为{1,2,3,4,5}

rand5 - 1的范围为{0,1,2,3,4}

(rand5 - 1) * 5的范围为{0,5,10,15,20}

那么,rand5 + (rand5 - 1) * 5 的范围为{1,2,3,4,5,6,7,8,9,10,…, 25},即1~25出现概率均为1/25,截断大于21的部分,然后模7并加1,即为rand7

#include <cstdio>
#include <cstdlib>
#include <ctime>
using namespace std;

int rand5() {
	return rand() % 5 + 1;
}

int rand7() {
	int res;
	do{
		res = rand5() + (rand5() - 1) * 5;
	} while(res > 21);
	return res % 7 + 1;
}


int main() {
	srand(time(0)); // 设置随机种子,使随机结果不固定
	printf("rand5的随机结果:\n");
	for (int i = 0; i < 10; i++) {
		printf("%d ", rand5());
	}
	
	printf("\n\nrand7的随机结果:\n");
	for(int i = 0; i < 10; i++) {
		printf("%d ", rand7());
	} 
	return 0;
}

rand5实现rand7

2. rand5生成rand70

现在考虑rand5生成rand70,用上述方法只能得到1~25的数,但是70大于25该怎么办?

(rand5 - 1) * 25的取值范围为{0,25,50,75,100},与1~25的数相加,可以得到1~125的随机整数,且每个数的出现概率相同,再截断大于70的部分,即为rand70

#include <cstdio>
#include <cstdlib>
#include <ctime>
using namespace std;

int rand5() {
	return rand() % 5 + 1;
}

int rand70() {
	int res;
	do{
		res = rand5() + (rand5() - 1) * 5 + (rand5() - 1) * 25;
	} while(res > 70);
	return res;
}


int main() {
	srand(time(0)); // 设置随机种子,使随机结果不固定
	printf("rand5的随机结果:\n");
	for (int i = 0; i < 10; i++) {
		printf("%d ", rand5());
	}
	
	printf("\n\nrand70的随机结果:\n");
	for(int i = 0; i < 10; i++) {
		printf("%d ", rand70());
	} 
	return 0;
}

请添加图片描述

总结:

r a n d n + ( r a n d n − 1 ) ∗ n randn + (randn - 1) * n randn+(randn1)n 可以生成 1 ~ n 2 1~n^2 1n2的随机整数

r a n d n + ( r a n d n − 1 ) ∗ n + ( r a n d n − 1 ) ∗ n 2 randn + (randn - 1) * n + (randn - 1) * n^2 randn+(randn1)n+(randn1)n2 可以生成 1 ~ n 3 1~n^3 1n3的随机整数

⋯ \cdots

r a n d n + ( r a n d n − 1 ) ∗ n + ⋯ + ( r a n d n − 1 ) ∗ n i randn + (randn - 1)*n + \cdots + (randn - 1) * n ^i randn+(randn1)n++(randn1)ni 可以生成 1 ~ n i + 1 1~n^{i+1} 1ni+1的随机整数

因此对于n < m的情况,可以使用 r a n d n randn randn不断的加上 ( r a n d n − 1 ) ∗ n i ( i = 1 , 2 , 3 , . . . ) (randn - 1) * n^i(i = 1, 2, 3, ...) (randn1)nii=1,2,3,...,直至 n i + 1 ≥ m n^{i+1} ≥ m ni+1m,然后截断大于m的最大倍数的部分(该倍数要小于等于 n i + 1 n^{i+1} ni+1),最后模m并加1即可得到 r a n d m randm randm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值