映射方法一:(点集来表示每个格(row,column))
(1,1) | (1,2) |
(2,1) | (2,2) |
(3,1) | (3,2) |
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
pos_num=(row-1)*3+column
反过来的对应关系:
row=pos_num/3(向上取整)
column=pos_num%3
这种映射方法的一种直观表现,我认为可以用排队来形式表现。
(1,1)(1,2)(2,1)(2,2)(3,1)(3,2)
||
1 2 3 4 6 7 8 9
a)先根据row占位,应为一共有3行,而且没行的元素一样,所以把数组3等分成小片.让row来占每个片的头一个位置(first_pos_num=(row-1)*3+1)。
1 | 2 | 3 |
{1 2 3} | {4 5 6} | {7 8 9} |
(1,1) | (1,2) | (1,3) |
{1 | 2 | 3} |
这种映射原理简单,但是在编程应用确实非常广泛的。
示例一:已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10。
根据概率论,7个数来构造10个数的随机函数是不可能,因为样本空间明显不够。所以第一步就是增加样本空间。一种很简单是通过两次的rand7(),我们可以得到一个大小为49的集合。
{(1,1),(1,2),(1,3)……(7,7)}
接下来就是把这49个元素等分重组成10个小集合s1,s2,s3,s4,s5,s6,s7,s8,s9,s10.每个集合对一个1~10之间的一个数。接下来的问题又转化成了怎么等分?49怎么也不能整除10,但是要想概率一样就必须要每个小集合的元素一样。所以只能抛弃9个元素,剩下40,然后每个小集合拥有4个元素。抛弃那些元素,和怎么划分的方法很多。我觉得很秒的一种应用上述我提到的集合映射成数组的方式。
第一步,是先把原来的49个点,映射成数。映射公式(和上面的稍有不同):
num=(px-1)*7+(py-1)
{(1,1),(1,2),(1,3)……(7,7)} ==》{0,1,2,3,4,5……48}
抛弃40~48这个几个9个数,剩下0~39这40个数,然后顺序分割s1={0,1,2,3},s2={4,5,6,7},s3={8,9,10,11}……
因为转换成了数,所以可以利用数的简单除法计算就可以判定属于那个小集合。
set_num=num/4+1
整个程序:
#include<stdio.h>
int rand7()
{
return rand()%7+1;
}
int rand10()
{
int px,py;
do{
px=rand7()-1;
py=rand7()-1;
printf("px:%d py:%d\n",px,py);
}while(px*7+py>40);
return (px*7+py)/4+1;
}