等概率随机数实现:
现在我们需要得到使用一个函数f1,这个函数可以等概率返回1-5,在只可以使用f1的情况下我们将f1如何改造成返回1-7这个函数呢?
1:首先,我们先将1-5转化为0和1,那就是,f1函数返回值<3就返回0,等于三就重新走一遍程序,>3就返回1:这就是新的函数f(2)
*/
public static int f1(){
return (int)(Math.random()*5)+1; //等概率1-5
}
// 随机机制,只用f1生成只返回0和1的等概率函数二
public static int f2(){
int ans = 0;
do {
ans = f1();
}while (ans == 3);
return ans<3?0:1;
}
2:然后我们先得到0-7,7用二进制可以表示为111,0就是000,也就是我们将函数f(2)循环执行三次,最后得到的二进制数字就是等概率的0-7:这里的<<就是移位的意思,比如f(2)等于1的时候移位就是:100也就是4 f(2)等于0的时候移位就是:000也就是0,这里先<<2然后加一个<<1然后加一个<<0就可以保证获得一个0-7随机数等概率,这个函数我们叫做f(3)
//三次f2得到000~111做到更改率------>0-7
public static int f3(){
int ans = (f2()<<2)+(f2()<<1)+(f2()<<0);
return ans;
}
3:然后我们使用f(3)再做一次分割可以得到0-6,也就是函数一旦返回7就重来一次:这里是f(4)
// 0-6等概率返回
public static int f4(){
int ans = 0;
do {
ans = f3();
}while (ans==7){
return ans;
}
}
同理我们想要将3-19变成20-56,就可以先将3-19转化为0和1也就是从11分开,只要是11就重来一次,然后3-19变成了01等概率发生器,然后17-56我们怎么得到呢?就是先得到0-38,r然后加17就成了17-56,所以我们现在使用01发生器想办法得到0-39,2的6次方是64,也就是我们需要“扔”6次01发生器,然后就是一个0-63范围的随机数,然后我们只要大于39就重新再来一次,这样的函数就可以返回0-39,
group by 什么时候用?
- 当SELECT 后 既有 表结构本身的字段,又有需要使用聚合函数(COUNT(),SUM(),MAX(),MIN(),AVG()等)的字段,
就要用到group by分组,查询的限定条件里有需要用聚合函数计算的字段时也需要用分组 - WHERE和HAVING的区别,WHERE作用于全表,而HAVING只作用于分组的组内。