ios - 始终将 slider 归因于零而导致100%失败的算法

标签 ios swift xcode algorithm

这是(假设是)确保所有滑块值的总和总是的总和等于globalTotal的函数。

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

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

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

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或任何特定编程语言相关的问题,因此我将用数学公式和解释而不是代码段来回答。

我也不是很了解您的算法。例如在这一行:

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

您首先要乘以100,然后再除以100,这样就可以将所有这100个因子放在第一位!

但是,我想我了解您要实现的目标,而问题是没有通用的解决方案。在编写算法之前,您必须精确定义所需的行为,包括所有边缘情况

让我们定义:
  • vi 作为的值,即 -th滑块和
  • Δi作为 i的改变-第滑块的值

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

    情况1:

    对于所有滑块(除了您更改的滑块之外), 0

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

    ∑iΔi= 0

    如果您有3个滑条,则减少为:
  • Δ1+Δ2+Δ3= 0

  • 并且如果更改的滑块是 i = 1 的滑块,那么此要求将显示为:
  • Δ1= –((Δ2+Δ3)

  • 您希望滑块按比例调整,这意味着此更改Δ1不应在其他滑块上平均分配,而应取决于它们的当前值:
  • Δ2= – w2 *Δ1
  • Δ3= – w3 *Δ1

  • 规范的权重因子为
  • w2 = v2 /(v2 + v3)
  • w3 = v3 /(v2 + v3)

  • 这样我们得到:
  • Δ2= – v2 / /(v2 + v3)*Δ1
  • Δ3= – v3 /(v2 + v3)*Δ1

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

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

    情况2:

    vi = 0 至少适用于一个滑块,但并非所有滑块(您更改过的滑块除外)

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

    情况3:

    vi = 0 ,适用于所有滑块(已更改的滑块除外)

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

    v2 + v3 = 0

    这只是权重因子 wi 完全未定义这一事实的另一种体现。因此,您将必须手动定义在这种情况下将发生的情况。

    在这种情况下,最合理的做法是将更改平均分配到所有滑块上:

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

    其中 n 是滑块的数量(不包括已更改的滑块!)。通过这种逻辑,每个滑块都可以“共享”变更。

    既然我们已经清楚算法,您可以在代码中实现这些情况。这里以一些伪代码为例:
    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
        }
    }
    

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

    关于ios - 始终将 slider 归因于零而导致100%失败的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44365741/

    相关文章:

    swift - 从两个字典中删除非重复键

    swift - 无法在 swift 上扩展扩展添加的结构

    ios - iOS 8 和 Swift 中的 MapKit

    ios - Realm移动平台打造通用 Realm

    ios - 当我在 xCode 上更改我的包 ID 时,该应用程序无法正常运行 - PhoneGap

    iphone - 使用协议(protocol)和委托(delegate)在 View Controller 之间传递数据

    swift - 为什么这个函数给我一个 "Command Failed due to signal"错误?

    XCode 的文档提示 "File Not Found"但给出正确的结果

    objective-c - 一对多关系之间的核心数据结构

    ios - 核心数据正在保存托管对象,但数据在应用程序启动之间不会持续存在