前言
在开发一些办公类的系统中,我会遇到这种需求,需要生成随机分数和权重,权重的和是固定的,并且不同的项目有多个权重,这是不确定的。因此就有这种逻辑也就是需要生成多个随机数,和是固定为某个值,因此需要个算法去统一这个
代码实现
首先需要产生随机的算法,采用的是random 产生随机数
public static int getrandom(int MIN, int MAX) {
Random random = new Random();
return random.nextInt(MAX - MIN + 1) + MIN;
}
public static double getrandomDouble(double MIN, double MAX) {
Random rand = new Random();
double result = MIN + (rand.nextDouble() * (MAX - MIN));
result = (double) Math.round(result * 10) / 10;
return result;
}
这是需要产生一个固定范围内的随机数。Random.nextInt计算的
- getrandom 计算int 是利用的是nextInt 随机产生某个范围内的整数 ,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含0而不包含n;但如果要想取值范围, 需要取一个 最小值,作为固定数,然后 在范围内 固定变化,例如 取最大为10 最小值2的随机数, 那么我们固定最小是2,其余的变化数,在0到8上变化
- getrandomDouble 原理是一样的,但是有点不一样的是,我想保留小数点1位,因此采用Math.round(result * 10) / 10; 进行计算
然后就是取固定和的随机数
public static List<Integer> getWeight(int num) {
List<Integer> result = new ArrayList<Integer>();
if (num == 1) {
result.add(10);
return result;
} else {
int num1 = getrandom(1, (10 / num + 1));
result.add(num1);
int total = 10;
for (int i = 1; i < num; i++) {
total = total - num1;
while (total < 1) {
int max = Collections.max(result);
result.set(result.indexOf(max), 1);
int s = result.stream().map(e -> e).reduce(Integer::sum).get();
total = 10 - s;
}
if (i != num - 1) {
num1 = getrandom(1, total);
result.add(num1);
} else {
result.add(total);
}
}
}
return result;
}
上面的例子我用的取1到(10 / num + 1) 之间取随机数,这里可以保证第一次产生的数不致过大,当然也可以不需要
List<Integer> result = new ArrayList<Integer>();
int num1 = getrandom(1, (10 / num + 1));
result.add(num1);
建立一个权重数组来存储权重,首先获得一个权重添加进去
然后从1开始循环下面的次数 产生随机数
这个地方需要不断修正数据,例如 总共循环3次,然后第一次产生到4 然后第二就产生了6,那第三次 我们的getrandom 就有问题了,在加上也不可能产生为0的数,因此解决方案就是 是要取到前面的最大数,进行修正为最小是1,不断进行修正 从而保证数据正常时就可以了
for (int i = 1; i < num; i++) {
total = total - num1;
while (total < 1) {
int max = Collections.max(result);
result.set(result.indexOf(max), 1);
int s = result.stream().map(e -> e).reduce(Integer::sum).get();
total = 10 - s;
}
if (i != num - 1) {
num1 = getrandom(1, total);
result.add(num1);
} else {
result.add(total);
}
}
当i指针不等于最后时,直接添加进去就行,这就做好了,产生多个1到10的随机数但随机数的总数等于10
然后把代码优化了一下
public static List<Integer> getWeight(int num, int max, int min) {
List<Integer> result = new ArrayList<Integer>();
if (num == 1) {
result.add(max);
return result;
} else {
int num1 = getrandom(min, (max / num + 1));
result.add(num1);
int total = max;
for (int i = 1; i < num; i++) {
total = total - num1;
while (total < min) {
int maxc = Collections.max(result);
result.set(result.indexOf(maxc), min);
int s = result.stream().map(e -> e).reduce(Integer::sum).get();
total = max - s;
}
if (i != num - 1) {
num1 = getrandom(min, total);
result.add(num1);
} else {
result.add(total);
}
}
}
return result;
}
比如说我们循环8次,总数为10,不能将修正最小值设为4 ,那就会导致死循环的。这个是很简单的,大家应该都可以想到
总结
最后做了一个读取表格分数并计算 得分的demo,主要FractionWord 类中操作
源码地址