1

我有这个问题,我想保留一个值列表并将它们标准化,以便所有值的总和为 1。

我发现了这个问题,但有一个区别。我想要 1 个固定的值。因为,有 4 个 GUI 滑块,我拖了一个。其他 3 个应相应更新,以使总和为 1。

// Let's keep 0.6 fixed and try to normalize the rest
List<float> categories = new List<float>() { 0.6f,0.3f,0.25f,0.25f };

// find the max value of the rest of the values that is not the fixed number
float maxval = categories.Where(s => s != 0.6f).Max();

if (maxval != 0) // check if not all other 
{
    // calculate the ratio
    float ratio = (1 - 0.6f) / maxval;

    foreach (float s in categories)
    {
        if (s != 0.6f)
        {
            s *= ratio;
        }
    }
}
else // all values are 0, so just add the rest value
{
    // do something else that is correct
}

不幸的是,这个例子将返回:

{ 0.6f, 0.4f, 0.33f, 0.33f } => sum is 1.66f

我有一些误解。有人可以给我一个线索,告诉我如何将其余的值归一化为其余的总和(0.4f),以便所有值的总和为 1?

4

2 回答 2

5

你计算错误。

如果你有 4 个元素,其中 1 个是固定的,并且总和需要为 1,你会这样:

ratio = (1-fixedElement) / sumOfAllOtherElements;

EachNonFixedElement *= ratio;

您仅使用最大值计算比率,但您需要使用所有非固定元素的总和来计算它。

于 2013-09-06T15:21:08.717 回答
0

除其他问题外,此循环并没有达到您的预期:

foreach (float s in categories) {
    if (s != 0.6f) {
        s *= ratio;
    }
}

s是来自 的值之一的本地副本categories。您修改副本,然后它超出范围,您的新值消失。你从未修改过categories.

C#foreach不能用于修改集合。

此外,为避免累积较大的舍入误差,您应该存储到一个新的集合中并且不要替换 中的值categories,至少在拖动操作结束之前。

于 2013-09-06T16:14:41.663 回答