我正在尝试创建一个具有设定长度的数字数组,定义该集合中的最小和最大数字,并让函数确定其间的其余数字。关键在于该数组的总和必须等于预定值。诀窍是弄清楚该函数是如何工作的。
我找到了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;
}
第一部分尝试并分配值,但最终得到的值总是大于或小于输入量,因此方程的第二部分可以解决这个问题。虽然看起来有点不干净,而且余数的分配方式有点随意,所以纯数学解决方案会很棒。
我开始想知道我是否需要微积分,因为我基本上有积分(数组值的总和),积分的范围(最小值和最大值),现在有找出曲线的公式。不过,目前这可能有点过分了。
感谢您的参与!
最佳答案
这个怎么样?首先以第一个成员为最小值、第二个成员为最小值 + 1、第三个最小值 + 2 等方式创建集合。然后将集合中的数字相加,并从预定值中减去总和。然后将减法结果分配给集合中的所有数字,如下所述。
Set makeSet(int preDet, int min, int max, int setLength)
{
if((max + max - setLength + 1) * setLength / 2 < preDet) return null;
if((min + min + setLength - 1) * setLength / 2 > preDet) return null;
Set set = Set(setLength);
int val = min;
for (int i = 0; i < setLength; i++)
{
set[i] = val++;
}
int sum = (min + val - 1) * setLength / 2;
int dev = preDet - sum;
if(dev)
{
int adj = dev / setLength;
if(dev % setLength) adj++;
for(int i = setLength -1; dev; i--)
{
if(adj > dev) adj = dev;
set[i] += adj;
dev -= adj;
}
}
return set;
}
关于javascript - 如何返回一个值数组,其总和等于指定数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41752962/