【问题标题】:How can I scale an array of values while maintaining a minimum value?如何在保持最小值的同时缩放一组值?
【发布时间】:2014-06-03 23:00:57
【问题描述】:

所以我有一组值需要按比例缩小,同时保持缩放值的最小值。

例如,假设我有一个值数组[1, 1, 3, 5],最小比例因子为.2

通过规范化数组,我们得到数组[.1, .1, .3, .5]。但是,请记住最小比例因子,我们将有值 [.2, .2, .3, .5],它加起来是 1.2,而不是 1

我的想法是遍历数组并首先将所有低于最小值的值设置为最小值,保留一个进位变量以确定仍然需要重新分配多少到数组中超过最低限度。

对于所有超过最小值的值,根据进位变量缩放它们的值,然后从它们的值中减去该值。

因此,对于上面的示例,我们将从.3 中减去3/8 * .2,并从.5 中减去5/8 * .2 以得到[.2, .2, .225, .375]

还有其他方法可以更有效地做到这一点吗?还是另一种缩放剩余值的方法?


编辑:对不起,缩放可能是不正确的术语,但最终数组的值将以这样一种方式进行划分,即它们的值相对于总值会发生变化。

我将解释具体的实现,以便问题更清楚:

我有很多帖子,每个帖子都会在淡出之前显示一段时间,然后再显示下一个帖子。我希望帖子之间的延迟取决于每个帖子中 words 的数量,但也被限制在至少某个最小值。

要显示所有帖子有一个总时间,并且应该在所有帖子之间分配时间。

【问题讨论】:

  • ???如果要缩放,则永远不要添加或减去...也许您的意思是其他类型的东西,不是缩放,或者不是指“最小”值,而是某种分辨率或粒度...您能解释一下吗?你在做什么。
  • 如果有最小值限制,那么你不能保证项目的总和等于1.0。
  • @miguel-svq 我用更多信息编辑了我的帖子。如果您需要更多信息,请告诉我!
  • 在 google 中搜索 Thales 和几何。我认为这比我写答案要快...
  • 如果您需要缩放 6 个值的数组以求总和为 1,同时保持最小值为 0.2,该怎么办?也许您可以告诉我们为了什么您需要“缩放”这个向量,以便我们为您提供适当的解决方案。

标签: javascript arrays algorithm math


【解决方案1】:

我希望帖子之间的延迟取决于每个帖子中的字数,但也限制在至少某个最小值。

显示所有帖子的总时间,并且应该在所有帖子之间分配时间。

你不能保证你会满足这两个要求。如果您有 30 个帖子,每个帖子必须显示至少 1 秒,并且仅显示 20 秒,那么 不可能 同时满足这两个要求。您必须:

  1. 延长总时间;或
  2. 减少最短时间

【讨论】:

    【解决方案2】:

    我们有一个样本集s = [ 1 1 3 5 ],我们正在寻找一个函数f(x),它接受单个样本并返回显示时间。

    要求Sum(Map(s, f)) = 1.0,(即所有s[i]的f(s)之和)以及所有s[i]s[i] >= minVal,首先考虑线性函数

    f(x) = ax + b
    

    最低限度

    a.xmin + b = minVal
    b = minVal - a.xmin
    

    总和:

    total = Sum(f(x) for x in s)
          = Sum((a*x + b) for x in s)
          = b*len(s) + Sum(a*x for x in s)
          = b*len(s) + a * Sum(s)
    1 = b*len(s) + a * Sum(s)
    a = (b * len(s) - 1.0) / Sum(s)
    

    替换

    1 = b*len(s) + a * Sum(s)
    1 = (minVal - a.xmin) * len(s) + a * Sum(s)
    1 = minVal * len(s) - xmin * len(s) * a + Sum(s) * a
    1 - (minVal * len(s)) = (Sum(s) - xmin*len(s)) * a
    a = (1 - (minVal * len(s))) / (Sum(s) - xmin*len(s))
    

    给定一个,

    b = minVal - a.xmin    
    

    因此在 javascript 中我们可以有一个函数工厂来给你一个缩放函数 f,给定一个样本集 s:

    function makeScalingFun(s, minVal) {
       var total = s.reduce(function(a, b) { return a + b; });
       var xmin = s.reduce(function(a, b) { return Math.min(a,b); });
       // f(x) = ax + b
       var a = (1.0 - (minVal * s.length)) / (total - xmin * s.length)
       var b = minVal - a * xmin
       var f = function(x) {
          return a * x + b;
       };
       return f;
    }
    

    并在使用中:

    var scaler = makeScalingFun(s, 0.2);
    console.log("Index, Value: Calced Delay");
    for(var i = 0; i < s.length; ++i) {
        console.log(i + ", " + s[i] + ": " + scaler(s[i]));
    }
    

    结果:

    Index, Value: Calced Delay
    0, 1: 0.2
    1, 1: 0.2
    2, 3: 0.26666666666666666
    3, 5: 0.3333333333333333 
    

    如果您有进一步的要求,您可以使用它们来构造二次目标函数而不是线性目标函数等。

    请注意,最小值总是会得到 minVal 延迟,这可能不太现实。考虑修改为使用 xmin 的常量值,例如0,因此,如果您有 3 个 450、451 和 452 的帖子,您不会因为第一个帖子最短而延迟相对较小。

    【讨论】:

      【解决方案3】:

      我会采取以下方法:

      假设您具有示例中的值:[1 1 3 5]。值的总和是10

      因此,将所有值除以10 并更正低于最小值的值。跟踪更正值的数量。在这种情况下是2。将2 乘以.2。那是.4

      现在,1 - .4 = .6 应该除以值 3535 之和为 8。因此,将每个未校正的原始值除以 8 并乘以 .6:例如3 / 8 * .6.

      这将为您提供标准化的值列表:[.2 .2 .225 .375]

      【讨论】:

        【解决方案4】:

        显然,您无法按照通常的含义对术语进行缩放,因为您最终可能会得到比最短时间少的倍数。如果帖子数量*最短时间超过您的总可用时间,您也会遇到麻烦。

        但假设不是...我建议给每篇文章的最短时间加上与较长文档中额外单词数成正比的额外时间。因此,给定值 [1 1 3 5] 并且要求最小值为 0.2...

        1) Subtract the minimum value from each value to give [0 0 2 4]
        2) Normalize this to give [0 0 0.333 0.667]
        3) Scale by (1 - 4*0.2) (that is 1 - number_of_values*min_time) to give [0 0 0.0667 0.133333]
        4) Finally add the minimum to each value to give [0.2 0.2 0.267 0.333]
        

        现在每个帖子都有一个基本时间加上一个与其额外长度成比例的额外时间。

        【讨论】:

          猜你喜欢
          • 2018-11-12
          • 1970-01-01
          • 1970-01-01
          • 2014-08-19
          • 2012-08-02
          • 1970-01-01
          • 1970-01-01
          • 2023-03-28
          • 1970-01-01
          相关资源
          最近更新 更多