【问题标题】:Function to normalize any number from 0 - 1标准化从 0 - 1 的任何数字的函数
【发布时间】:2017-02-08 03:56:25
【问题描述】:

我正在尝试创建一个函数,该函数接受一个数字并将其从 0 到 1 标准化,介于其最小和最大范围之间。例如:

如果我想在 5 到 15 之间标准化 10 的值,我称之为:

val = 10; normalize(val, 5, 15); 返回 0.5

在 -10 和 5 之间标准化一个值 0

val = 0; normalize(val, -10, 5); 返回 0.666

这是我想出的功能:

function normalize(val, min, max){
  // Shift to positive to avoid issues when crossing the 0 line
  if(min < 0){
    max += 0 - min;
    val += 0 - min;
    min = 0;
  }
  // Shift values from 0 - max
  val = val - min;
  max = max - min;
  return Math.max(0, Math.min(1, val / max));
}

我的问题是:这是标准化一维值的最有效方法吗?我将以 60fps 每帧调用这个函数几千次,所以我希望尽可能优化它以减少计算负担。我一直在寻找归一化公式,但我找到的都是 2 维或 3 维解决方案。

【问题讨论】:

  • 我看不出你为什么要单独处理负分钟数,
  • 数组的最小值和最大值是否始终相同?
  • @redneb 哇,你是对的!我是在没有真正测试的情况下先发制人地这样做的。它可以在不切换到 > 0 的情况下工作
  • @NinaScholz min 和 max 会根据我调用它的位置而改变。有时是-100, 0,有时是-3, 781,等等。
  • @MarcoDelValle 所以只要去掉负最小值的特殊处理就可以了。

标签: javascript performance math normalization


【解决方案1】:

为什么不只是:

function(val, max, min) { return (val - min) / (max - min); }

【讨论】:

  • 太好了,谢谢!这似乎是最简单的方法。我用 if 语句把事情复杂化了。但是,我仍然想将值限制在 0 和 1 之间,所以我正在考虑做 return Math.max(0, Math.min(1, val-min / max-min))
  • @MarcoDelValle 只要val 实际上介于minmax 之间,结果将始终介于0 和1 之间。
  • @Keiwan 我知道。问题是val 并不总是介于minmax 之间,所以我需要一种方法来防止它返回负数或任何大于 1 的值
  • @MarcoDelValle:不要忘记在(max-min) 周围加上括号。
  • @Keiwan 如果我想要介于 -1, 1 之间的值怎么办
【解决方案2】:

Nathan Bertons 的答案与预配置函数一起用于具有相同minmax 值的某些值,您可以使用它。

function normalize(min, max) {
    var delta = max - min;
    return function (val) {
        return (val - min) / delta;
    };
}

console.log([5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].map(normalize(5, 15)));

【讨论】:

    【解决方案3】:

    当我想用已知的最小值、最大值对两个范围之间的值进行归一化时,我更喜欢使用这个公式。您可以添加检查来约束输入,但如果输入超出范围的值,这将正确计算与新范围的差异。

    /**
     * Normalizes a value from one range (current) to another (new).
     *
     * @param  { Number } val    //the current value (part of the current range).
     * @param  { Number } minVal //the min value of the current value range.
     * @param  { Number } maxVal //the max value of the current value range.
     * @param  { Number } newMin //the min value of the new value range.
     * @param  { Number } newMax //the max value of the new value range.
     *
     * @returns { Number } the normalized value.
     */
    const normalizeBetweenTwoRanges = (val, minVal, maxVal, newMin, newMax) => {
      return newMin + (val - minVal) * (newMax - newMin) / (maxVal - minVal);
    };
    
    const e = document.getElementById('result');
    e.innerHTML = normalizeBetweenTwoRanges(10, 5, 15, 0, 1);
    &lt;span id="result"&gt;&lt;/span&gt;

    【讨论】:

    【解决方案4】:

    使用Nathan Bertons的回答,你必须验证max-min是否等于0,否则返回NaN:

    function (val, max, min) { 
        if(max - min === 0) return 1; // or 0, it's up to you
        return (val - min) / (max - min); 
    }
    

    您可以使用generalization 来限制数据集中任意点 a 和 b 之间的值范围:

    function (val, max, min) {
        if(max - min === 0) return a; // or b, it's up to you
        return a + (((val - min) * (b-a)) / (max - min));
    }
    

    【讨论】:

    • 如果 max - min 具有相同的值,则它们将等于零,你不可能给 max = 5min = 5
    【解决方案5】:

    我将完成 Nina Scholz 的答案,您可以使用下划线库来查找数组的最小值和最大值,您可以使用如下,或者创建自己的(简单的方法和简单的循环):

    如果您使用的是 nodeJS,您需要使用命令 npm install underscore 安装下划线并使用命令 var _ = require('underscore/underscore'); 或者您可以在 html 上导入库并在您的网络上使用

    function min(arr) { if (!arr.length) return null; var minValue = arr[0]; for (var item of arr) { if (item maxValue) maxValue = item; } return maxValue; } var array = [1, 2, 3, 4, 5, 6, 7, 8, 9]; function normalize(min, max) { var delta = max - min; return function (val) { return (val - min) / delta; }; } function normalizeArray(array) { var minValue = min(array); //if you use underscore _.min(array) var maxValue = max(array);//if you use underscore _.max(array) return array.map(normalize(minValue, maxValue)); } console.log(normalizeArray(array));

    【讨论】:

    • 抱歉在这里你也找到了 max 函数 :) function max(arr) { if (!arr.length) return null; var maxValue = arr[0]; for (var item of arr) { if (item > maxValue) maxValue = item; } 返回最大值; }
    【解决方案6】:

    最大-最小限制

    function normalize(min, max) {
       const delta = max - min;
       return val => ( (val < min? min: (val > max? max : val)) - min ) / delta;
    }
    console.log([-2,3,5, 6, 7, 8, 9, 10,11,23].map(normalize(0, 10)));
    // [
    

    输出:[0, 0.3, 0.5, 0.6, 0.7, 0.8, 0.9, 1、 1、 1 ]

    【讨论】:

    • 更简单:return Math.max(0, Math.min(1, val-min / max-min))
    【解决方案7】:

    如果您想要一种更动态的方法,您可以在其中指定最大范围,那么这可以是这里的解决方案,在这个示例中,我们将我们的数据标准化在 0 到 100 的范围内

        let a = [500, 2000, 3000, 10000];
    
        function normalize(data, arr_max, arr_min, newMax){
            return data.map(d => {
                return newMax * ((d - arr_min)/(arr_max - arr_min))
            })
        }
    
    
    console.log(normalize(a, 10000, 500, 100))
    

    【讨论】:

    • 我觉得这只会使接受的答案过于复杂。我从来没有要求数组映射,也没有乘以 newMax 值。
    猜你喜欢
    • 2017-03-14
    • 1970-01-01
    • 2016-12-29
    • 2014-03-03
    • 2016-10-31
    • 2017-06-27
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多