我正在尝试生成等于 100(%) 的数字,但所有数字之间必须至少有 4 个数字。因此,如果我生成 4 个数字,它们必须像这样,例如 [22,28,15,35] 而不能像这样 [22,28,20,30] 因为 28-30 和 22-20 之间的差异小于 4。
我能够将生成数字的方法放在一起,看起来像这样。
generate (max, many) {
this.numbers_array = []
this.normalized_numbers_array = []
this.sum = 0
for (let i = 0; i < many; i++) {
this.numbers_array.push(Math.random())
this.sum += this.numbers_array[i]
}
this.remaining = max
for (let i = 0; i < this.numbers_array.length; i++) {
this.outcome= (this.numbers_array[i] / this.sum) * max
this.normalized_numbers_array[i] = Math.floor(this.outcome)
this.remaining -= this.normalized_numbers_array[i]
if (i + 1 == this.numbers_array.length) {
while (this.remaining > 0) {
this.normalized_numbers_array[i]++
this.remaining--
}
}
}
}
并且工作正常。我的下一个方法是尝试通过两个 for 循环和 if 语句将规范化数字相互比较。然后根据彼此之间的数字差异,我希望对正在比较的两个数字将 2% 添加到一个并从另一个减去 2%。然后我将它们放入我想再次归一化的新数组中。
for (let i = 0; i < this.normalized_numbers_array.length; i++) {
for (let j = i + 1; j < this.normalized_numbers_array.length; j++) {
if (Math.abs(this.normalized_numbers_array[i] - this.normalized_numbers_array[j]) < 5) {
//do something
if (this.normalized_numbers_array[i] > this.normalized_numbers_array[j]) {
//do something
} else if (this.normalized_numbers_array[i] <= this.normalized_numbers_array[j]) {
//do something
}
}
}
不过,这种方法是有缺陷的。通过添加或子结构,我可以创建小于 4 的新差异。例如 [35,18,26,21]->[35,16,26,23] 26 和 23 之间的差异更改后为3。
我的想法是创建另一个循环,只要存在差异就会继续下去。但我不确定这是否有效。所以我想知道是否有更好的解决方案来解决这个问题——也许能够从一开始就生成大小不同的数字,而不必在之后更改它们。
最佳答案
- 从同一范围内生成四个统一的随机数
- 缩放它们,使它们加起来达到 76(100 - 分隔符,见下文);根据需要随机调整以解决剩余问题
- 插入分隔符:排序,然后第一个加 4,第二个加 8,最后一个加 12(第 0 个不调整)。
例子
- 生成
[102, 387, 386, 284]
- 比例:
[102, 387, 386, 284] * 76/(102 + 387 + 386 + 284)
计算结果为[6, 25, 25, 18]
- 调整:那就只有74了,所以随机给两个元素加上
1
:[6, 25, 26, 19]
- 排序:
[6, 19, 25, 26]
- 插入分隔符:
[6, 23, 33, 38]
加起来为 100,保证至少相隔 4,[编辑] 很少的循环(以确保不被零除),并且对分布的任意干扰尽可能少。出于好奇,这是它的样子:
function f() {
let q, s;
while (!s) {
q = Array.from({length: 4}, () => Math.random());
s = q.reduce((a, e) => a + e);
}
q.forEach((e, i, q) => q[i] = (e * 76 / s)|0);
s = q.reduce((a, e) => a + e);
while (s < 76) {
q[(Math.random() * 4)|0]++; s++;
}
q.sort((a, b) => a - b);
q.forEach((e, i, q) => q[i] += i * 4);
return q;
}
const N = 100000;
function draw() {
const labels = ["#0", "#1", "#2", "#3", "Any"];
const colours = ["red", "orange", "green", "blue", "black"];
const data = Array.from({length:5}, (e, i) => ({
label: labels[i],
borderColor: colours[i],
backgroundColor: i == 4 ? "rgba(0, 0, 0, 0.1)" : "rgba(0, 0, 0, 0)",
pointRadius: 0,
data: Array.from({length:100}, (e, i) => ({ x: i, y: 0 }))
}));
for (let s = 0; s < N; s++) {
const q = f();
q.forEach((e, i) => {
data[i].data[e].y++;
data[4].data[e].y++;
});
}
const ctx = document.querySelector('canvas').getContext('2d');
const myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: data
},
options: {
maintainAspectRatio: false,
animation: false,
legend: {
position: 'right'
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
type: 'linear',
ticks: {
beginAtZero: true,
max: 100
}
}]
}
}
});
};
draw();
document.querySelector('canvas').addEventListener('dblclick', draw);
<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0/dist/Chart.min.js"></script>
<canvas width="400" height="180"/>
关于javascript - 生成等于 100 但两个数字之间的差必须大于 4 的 m 个数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56850470/