标准化从 0 - 1 的任何数字的函数
Posted
技术标签:
【中文标题】标准化从 0 - 1 的任何数字的函数【英文标题】:Function to normalize any number from 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 所以只要去掉负最小值的特殊处理就可以了。
【参考方案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
实际上介于min
和max
之间,结果将始终介于0 和1 之间。
@Keiwan 我知道。问题是val
并不总是介于min
和max
之间,所以我需要一种方法来防止它返回负数或任何大于 1 的值
@MarcoDelValle:不要忘记在(max-min)
周围加上括号。
@Keiwan 如果我想要介于 -1, 1 之间的值怎么办【参考方案2】:
将Nathan Bertons 的答案与预配置函数一起用于具有相同min
和max
值的某些值,您可以使用它。
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);
<span id="result"></span>
【讨论】:
请小心,因为这不支持负范围,这里有一个实现:***.com/a/51161208/930675 抱歉,它在 C# 中。【参考方案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 = 5
和 min = 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
值。以上是关于标准化从 0 - 1 的任何数字的函数的主要内容,如果未能解决你的问题,请参考以下文章