网上看到很多用轮盘算法,都是采用的如下图的模式,
1.随机出N个个体的值,
2.遍历统计sum
3.double类型存储单个概率。
4.合计概率。
但个人觉得其实完全没必要这么计算,一方面double类型的转换要花时间,另一方面多次遍历感觉不大好。
故试作了另一种轮盘算法,思路是取消概率分算,直接用sum值来对比。
对比了一下两种计算,新算法快了几十倍,有兴趣的可以验证一下,下面是运行截图与测试代码。
import java.util.Arrays;
public class RotaryDemo {
public static void main(String[] args) {
select1();
System.out.println();
select2();
}
/**
* 第一种算法,对应累计概率确定选择是哪个,由于概率大的拥有数值大,故被选择概率大
*/
private static void select1() {
long t1 = System.nanoTime();
int arr[] = new int[10];// 单个数值
double p[] = new double[10];// 计算概率
double p_sum[] = new double[10];// 累计概率,对应轮盘值
int sum = 0;
for (int i = 0; i < 10; i++) {
arr[i] = (int) (Math.random() * 100);
sum += arr[i];
}
p[0] = 1.0 * arr[0] / sum;
p_sum[0] = p[0];
for (int i = 1; i < arr.length; i++) {
p[i] = 1.0 * arr[i] / sum;
p_sum[i] = p_sum[i - 1] + p[i];
}
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(p));
System.out.println(Arrays.toString(p_sum));
double r = Math.random();
for (int i = 0; i < p_sum.length; i++) {
if (p_sum[i] > r) {
t1 = System.nanoTime() - t1;
System.out.println("选中第" + i + "个,概率为" + p_sum[i] + ",抽奖随机概率为:" + r + "费时:" + t1);
break;
}
}
}
/**
* 第二种算法,不算概率,只求合计,得出累计值
*/
private static void select2() {
long t1 = System.nanoTime();
int arr[] = new int[10];// 单个数值
int p_sum[] = new int[10];
int sum = 0;
for (int i = 0; i < 10; i++) {
arr[i] = (int) (Math.random() * 100);
if (i == 0) {
p_sum[i] = arr[i];
} else {
p_sum[i] = p_sum[i - 1] + arr[i];
}
sum += arr[i];
}
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(p_sum));
double r = Math.random();
int m = (int) (r * sum);
for (int i = 0; i < p_sum.length; i++) {
if (p_sum[i] > m) {
t1 = System.nanoTime() - t1;
System.out.println("选中:" + i + "个,概率为" + (arr[i] * 1.0 / sum) + ",抽奖随机概率为:" + r + "费时:" + t1);
break;
}
}
}