私は数を取り、その最小と最大の境界の間で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));
}
私の質問は、これが1次元の値を正規化する最も効率的な方法ですか?この関数をフレームごとに60fpsで数千回呼び出すので、できる限り最適化して計算の負担を軽減したいと思います。正規化の式を探しましたが、見つかったのは2次元または3次元の解だけです。
なぜだけではありません:
function(val, max, min) { return (val - min) / (max - min); }
同じmin
とmax
の値を持ついくつかの値に対して、事前設定された関数で Nathan Bertons の答えを使用すると、これを使用できます。
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)));
Nathan Bertons の答えを使用して、max-minがゼロに等しいかどうかを検証する必要があります。そうでない場合、戻り値は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)); }
既知の最小値、最大値で2つの範囲の間の値を正規化する場合、この式を使用することを好みます。入力を制約するためにチェックを追加できますが、範囲外の値が入力として与えられた場合、これにより新しい範囲との差が正しく計算されます。
/**
* 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>
Nina Scholzの答えを完成させます、アンダースコアライブラリを使用して配列の最小値と最大値を見つけ、次のように使用するか、独自の方法を作成できます(単純なループを使用した単純な方法):
nodeJSを使用している場合は、コマンドnpm install underscoreでアンダースコアをインストールし、コマンドvar _ = require('underscore/underscore');
で使用するか、ライブラリをHTMLにインポートしてWebで使用する必要があります。
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));