java生成多个随机数的和为固定值

前言

在开发一些办公类的系统中,我会遇到这种需求,需要生成随机分数和权重,权重的和是固定的,并且不同的项目有多个权重,这是不确定的。因此就有这种逻辑也就是需要生成多个随机数,和是固定为某个值,因此需要个算法去统一这个

代码实现

首先需要产生随机的算法,采用的是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 类中操作

源码地址

https://github.com/caozhou1/WordOperation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踩踩踩从踩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值