比如总金额100,规定兑换50份,每份的金额在1-2.5之间(可以等于界限值),怎么在50次发放完100块钱?
const 红包分配 = (总额, 总数, 范围) => {
const [ 最小值, 最大值 ] = 范围
let 分配结果 = []
let 已分配金额 = 0
let 已分配总数 = 0
while (已分配总数 < 总数 - 1) {
let 分配金额
do {
分配金额 = 最小值 + Math.random() * (最大值 - 最小值)
const 剩余平均 = (总额 - 已分配金额 - 分配金额) / (总数 - 已分配总数 - 1)
if (剩余平均 > 最小值 * 1.01 && 剩余平均 < 最大值 * .99) {
break;
}
} while (true)
分配结果.push(分配金额)
已分配金额 += 分配金额
已分配总数++
}
分配结果.push(总额 - 已分配金额)
return 分配结果
}
console.log(红包分配(100, 50, [1, 2.5]).map((n, i) => (i && i % 5 === 0 ? '\n' : '') + n.toFixed(2)).join(', '))
弄了个,有时有点超边界,大多数情况下随得比较平均
// java
static double START = 1.5d;
static double END = 2.5d;
public static void main(String[] args) {~~~~
double amount = 100d;
int n = 50;
double start = START;
double end = END;
double remain = amount;
double total = 0;
List<Double> list = new ArrayList<>();
for (int i = 0; i < n - 1; i++) {
double d = RandomUtils.nextDouble(start, end);
remain -= d;
total += d;
System.out.println(d);
list.add(d);
double ar = remain / (50d - i - 1);
start = Math.max(ar - 0.5d, START);
end = Math.min(ar + 0.5d, END);
}
System.out.println(remain);
total += remain;
list.add(remain);
System.out.println(list.size());
System.out.println(total);
}
2 回答5.1k 阅读✓ 已解决
4 回答1.2k 阅读✓ 已解决
4 回答1.2k 阅读✓ 已解决
1 回答2.5k 阅读✓ 已解决
1 回答1.2k 阅读✓ 已解决
2 回答704 阅读✓ 已解决
2 回答1.7k 阅读
1 首先 平均分配,100/50 = 2,存入数组 [100]
2 循环若干次(次数 50次以上),随机数组一项
向下可减去额度是 add = x-1, 向上可增加额度是 sub = 2.5-x
随机确定是 向上还是向下,取减去 0-sub 或 /增加额度 0-add 随机值,调整值记为 delta
随机取数组另一项,执行反向操作,增加 或 减去 delta,若超出范围,则 保留差值,继续调整,直到 delta = 0