始终将滑块归因于零而导致100%失败的算法 [英] Algorithm to always sum sliders to 100% failing due to zeroes

查看:111
本文介绍了始终将滑块归因于零而导致100%失败的算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(假设是)一个函数,该函数确保滑块的多个值的总和始终加起来为 globalTotal

This is (supposed to be) a function which makes sure that the the sum of a number of slider's values always adds up to globalTotal.

用户可以手动将滑块值更改为 changer.value ,然后将该功能应用于 other 滑块的值,它可以确定其新滑块或 endVal

A slider value can be changed manually by the user to changer.value and then when applying this function to the values of the other sliders, it can determine their new or endVal.

它需要需要更改的滑块的 startVal 和更改后的滑块的原始值 changerStartVal 并可以通过加权确定其他值。

It takes the startVal of the slider which needs changing and the original value of the slider that changed changerStartVal and can determine the new value others by weighting.

问题和我的问题是。有时 remainingStartVals 可以为(当滑块更改一直移动到最大值时)或 startVal 可以为(将更改的滑块移到零,然后再移动另一个滑块)。发生这种情况时,我分别得到了除以零或乘以零的结果。两者都是不好的,并导致不正确的结果。有没有简单的方法可以解决此问题?

The problem and my question is. Sometimes remainingStartVals can be zero (when the slider changing gets moved all the way to maximum) or startVal can be zero (when the slider changing is moved to zero and then another slider is moved). When this happens I get a divide-by-zero or a multiply-by-zero respectively. Both of which are bad and lead to incorrect results. Is there an easy way to fix this?

func calcNewVal(startVal: Float, changerStartVal: Float) -> Float {

    let remainingStartVals = globalTotal - changerStartVal

    let remainingNewVals = globalTotal - changer.value

    let endVal = ((startVal * (100 / remainingStartVals)) / 100) * remainingNewVals

    return endVal

}


推荐答案

这是一个数学问题,不是与Swift或任何特定编程语言相关的问题,因此我将用数学公式和解释而不是代码段来回答。

This is a mathematical problem, not a problem related to Swift or any specific programming language so I'll answer with mathematical formulas and explanations rather than code snippets.

p>

我也不是很了解您的算法。在此行中的示例:

I don't really understand your algorithm either. For example in this line:

let endVal = ((startVal * (100 / remainingStartVals)) / 100) * remainingNewVals

您首先要乘以100,然后再除以100,所以您可以将所有这100个因子留在

you first multiply by 100 and then divide by 100, so you could just leave all these 100 factors out in the first place!

但是,我想我知道您要实现的目标,而且问题在于>不是通用解决方案。在编写算法之前,必须准确定义 的行为方式,包括所有边沿情况

However, I think I understand what you're trying to achieve and the problem is that there is no generic solution. Before writing an algorithm you have to define exactly how you want it to behave, including all edge cases.

让我们定义:


  • v i i 滑块的值和

  • Δ i em> 作为第 i 个滑块的值的变化

  • vi as the value of the i-th slider and
  • Δi as the change of the i-th slider's value

然后,您必须考虑以下情况:

Then you have to think of the following cases:


0< v i ≤1 (所有滑条除外)

0 < vi ≤ 1 for all sliders (other than the one you changed)

这可能是您在考虑的常见情况。在这种情况下,您需要调整未更改的滑块的值,以使它们的总变化等于您滑块的变化 Δ更改 改变了。换句话说:

This is probably the common case you were thinking about. In this case you want to adjust the values of your unchanged sliders so that their total change is equal to the change Δchanged of the slider you changed. In other words:

i i Δ i = 0

如果您有3个滑块,则减少为:

If you have 3 sliders this reduces to:


  • Δ 1 2 3 = 0

  • Δ1 + Δ2 + Δ3 = 0

如果更改的滑块是 i = 1 的滑块,则此要求将显示为:

And if the slider that changed is the one with i = 1 then this requirement would read:


  • Δ 1 = –(Δ 2 + Δ 3

  • Δ1 = – (Δ2 + Δ3)

您希望滑块按比例调整 Δ 1 的变化不应在其他滑块上平均分配,而是取决于它们的当前值:

You want the sliders to adjust proportionally which means that this change Δ1 should not be distributed equally on the other sliders but depending on their current value:


  • Δ 2 = – w 2 1

  • Δ 3 = – w 3 1

  • Δ2 = – w2 * Δ1
  • Δ3 = – w3 * Δ1

标准权重因子为


  • w 2 = v 2 /(v 2 + v 3

  • w 3 = v 3 /(v 2 + v 3

  • w2 = v2 / (v2 + v3)
  • w3 = v3 / (v2 + v3)

因此我们得到:


  • Δ 2 = – v 2 /(v 2 + v 3 )*Δ 1

  • Δ 3 = – v 3 /(v 2 + v 3 )*Δ 1

  • Δ2 = – v2 / (v2 + v3) * Δ1
  • Δ3 = – v3 / (v2 + v3) * Δ1

因此,这些是适用于此特定情况的公式。

So these are the formulas to applied for this particular case.

但是,还有很多其他情况不适用于此方法:

However, there are quite a few other cases that don't work with this approach:


v i = 0 表示至少一个(但不是所有)滑块(不是您更改的滑块)

vi = 0 for at least one, but not all of the sliders (other than the one you changed)

在这种情况下,情况1 中的方法d仍然有效(再加上这样做是合乎逻辑的)。但是,如果滑块的值为零,则它的值永远不会改变。所有更改都将以> 0的值分布在滑块上。

In this case the approach from case 1 would still work (plus it would be the logical thing to do). However, a slider's value would never change if it's zero. All of the change will be distributed over the sliders with a value > 0.


v i = 0 (除了一个)

vi = 0 for all sliders (other than the one you changed)

在这种情况下,按比例的更改不起作用,因为根本没有信息可以将更改分布在滑块上。它们全为零!这实际上是您的零除问题:如果我们有3个滑杆,而滑杆1发生变化,我们将得到

In this case the proportional change doesn't work because there is simply no information how to distribute the change over the sliders. They're all zero! This is actually your zero division problem: In the case where we have 3 sliders and the slider 1 changes we'll get

v 2 + v 3 = 0

v2 + v3 = 0

这仅仅是事实,权重因子 w i 只是不确定的。因此,您必须手动定义在这种情况下将发生的情况。

This is only another manifestation of the fact that the weight factors wi are simply undefined. Thus, you'll have to manually define what will happen in this case.

在这种情况下,最可行的做法是将更改 evenly 在所有滑块上:

The most plausible thing to do in this case is to distribute the change evenly over all sliders:

Δ i = –(1 / n)*Δ 1

Δi = – (1 / n) * Δ1

其中 n 滑块(不包括已更改的滑块!)。按照这种逻辑,每个滑块都会获得变更的相同份额。

where n is the number of sliders (excluding the one that was changed!). With this logic, every slider gets "the same share" of the change.

现在我们很清楚了您可以在代码中实现这些情况的算法。这里以一些伪代码为例:

Now that we're clear with our algorithm you can implement these cases in code. Here some pseudo code as an example:

if sum(valuesOfAllSlidersOtherThanTheSliderThatChanged) == 0 {
    for allUnchangedSliders {
        // distribute change evenly over the sliders
        Δi = – (1 / n) * Δ_changedSlider
    }
}
else {
    for allUnchangedSliders {
        // use weight factor to change proportionally
        Δi = – v_i / ∑(v_i) * Δ_changedSlider
    }
}

请注意,您必须 开头缓存滑块当前状态的值(甚至更好),首先计算所有更改,然后成批应用所有更改。否则,您将使用刚刚计算出的值 v 2 ' 来确定值 v 3 ' ,这显然会导致错误的值。

Please be aware that you must cache the values of the current state of your sliders at the beginning or (even better) first compute all the changes and then apply all the changes in a batch. Otherwise you will use a value v2' that you just computed for determining the value v3' which will obviously result in incorrect values.

这篇关于始终将滑块归因于零而导致100%失败的算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆