【发布时间】:2017-01-19 22:33:42
【问题描述】:
我正在尝试创建一个具有一定长度的数字数组,定义集合中的最小和最大数字,并让函数确定其余数字之间的数字。关键是这个数字数组的总和必须等于预定值。诀窍在于弄清楚该函数是如何工作的。
我找到了this on stack overflow,得到了以下功能:
export const distributeValues = (amount, weights=[]) => {
const distributedAmounts = []
let totalWeights = weights.reduce( (a,b) => a + b)
weights.forEach( weight => {
const weightValue = parseFloat(weight)
const percentage = weightValue / totalWeights
const distributedAmount = Math.round(percentage * amount)
distributedAmounts.push(distributedAmount)
totalWeights -= weightValue
amount -= distributedAmount
})
return distributedAmounts
}
这似乎是一个好的开始,但实际上我需要倒退;我试图找出一个函数,它会给我传递给上述函数的权重。
现在,我有这个,一个分为两部分的功能(为冗余道歉):
export const getDistributions = (amount, distributions, modifier) => {
const values = []
let amountLeft = amount;
for (let i = 0; i < distributions; i++ ) {
const value = Math.max(Math.round((amountLeft / (modifier || 4))),1)
amountLeft -= value
values.push(value)
}
// -------------------------------------------- //
// --- correct for cases where total values --- //
// --- end up greater/less than amount --- //
// -------------------------------------------- //
let iterator = 0
let totalAssignedValue = values.reduce((a,b) => a+b);
const lastIndex = (values.length - 1);
const getIndex = (iterator, values) => {
return iterator > lastIndex ? iterator % lastIndex : iterator
}
while (totalAssignedValue > amount) {
iterator = getIndex(iterator)
if (iterator !== lastIndex && iterator !== 0 && values[iterator] > 1) {
values[iterator]--
}
iterator ++
totalAssignedValue = values.reduce((a,b) => a+b);
}
while (totalAssignedValue < amount) {
iterator = getIndex(iterator)
if (iterator !== lastIndex && iterator !== 0) {
values[iterator]++
}
iterator ++
totalAssignedValue = values.reduce((a,b) => a+b);
}
// -------------------------------------------- //
// -------------- end correction -------------- //
// -------------------------------------------- //
return values;
}
第一部分尝试并分配值,但最终我得到的值总是大于或小于输入量,因此等式的第二部分可以解决这个问题。不过看起来有点不干净,余数的分布方式有点随意,所以纯数学解决方案会很棒。
我开始怀疑我是否需要微积分,因为我基本上有积分(数组值的总和),积分的范围(最小值和最大值),现在有找出曲线的公式。不过,此时这可能有点过头了。
感谢您的意见!
【问题讨论】:
-
您需要了解的一件事是关于 JavaScript 如何存储数字,这会导致计算混乱(例如,0.1 + 0.2 !== 0.3)。参见例如this page, which explains some about the issue。
-
很好的电话.. 谢谢!
-
如果您包含示例输入和预期输出,将会有很大帮助。你说你想指定最小值和最大值,有多少和总和,但似乎没有参数。
-
基本上我正在尝试获取百分比分布。所以,总和必须等于 100,我想要的最小值是 1%。我一直使用 50% 作为最大值来测试,但它真的可以是任何东西。因此,我们的想法是获得,例如,一组 5 个不同的百分比,最小值 = 1%,最大值 = 50%,其余 3 个介于两者之间,只要集合总和为 100%
标签: javascript arrays distributed curve