Я рассчитываю среднее значение массива значений журнала (децибел, если это имеет значение) в JavaScript. Мне пришло в голову, что если числа являются логарифмическими значениями (где 55 - это 10, умноженное на 54), средний уровень в децибелах не будет средним от логарифмов. Какой лучший способ подойти к этому?
Ниже приведен код, в котором я обычно вычисляю среднее значение в JS. Какой бы изящный способ вычислить среднее значение массива лог-значений в JavaScript?
// These values are in decibels
const samples = [40, 50, 55, 80, 45];
document.getElementById('samples').innerText = JSON.stringify(samples);
let total = 0;
samples.forEach(value => {
total = total + value;
});
const average = total / samples.length;
document.getElementById('avg').innerText = JSON.stringify(average);
<div>
Decibel samples:
<span id="samples"></span>
</div>
<div>
Average:
<span id="avg"></span>
</div>
3 ответа
Основано на определении децибела (@schnauss) децибела в Википедии. Есть 2 определения: мощность и амплитуда децибел. Я смотрю на мощность децибела.
Избавьтесь от логарифмов, найдите средний и повторно примените логарифм.
var samples = [40, 50, 55, 80, 45],
x = 0.0;
samples.forEach(value => {
x += Math.pow(10, value/10.0);
});
var average = x / samples.length,
logAverage = 10 * Math.log10(average);
console.log(logAverage);
Результат ~ 73 дБ
Я думаю, это подходящая формула. (Децибелы могут быть довольно запутанными.)
const mean = (ns) => ns.reduce((a, b) => a + b, 0) / (ns.length || 1)
const decibelAverage = (decibels) =>
10 * Math.log10(mean(decibels.map(n => 10 ** (n / 10))))
console.log(decibelAverage([40, 50, 55, 80, 45])) //~> 73.03013877157564
Дело в том, что децибел представляет 10-кратный логарифм базового-10 уровня мощности. (Существует также другой тип децибела. Если вам нужно, то где-то вокруг есть плавающий квадратный корень.)
Простой подход может состоять в том, чтобы инвертировать журнал в значения, сделать среднее значение, как обычно, и затем применить журнал к результату. Это может быть более эффективный способ выполнения этой операции, но если производительность не критична, вы можете попробовать ее.
Я не могу попробовать этот код, поэтому, если что-то пойдет не так, не стесняйтесь говорить что-нибудь! Любое предложение приветствуется.
РЕДАКТИРОВАТЬ: забыл заново сделать журнал в конце, просто добавил его
// These values are in decibels
const samples = [40, 50, 55, 80, 45];
//Undo the log. Be careful if base 10 is not the one you are using!
samples.forEach(function(element, index, array){
array[index] = Math.pow(10, element);
});
document.getElementById('samples').innerText = JSON.stringify(samples);
let total = 0;
samples.forEach(value => {
total = total + value;
});
const average = Math.log10(total / samples.length);
document.getElementById('avg').innerText = JSON.stringify(average);
<div>
Decibel samples:
<span id="samples"></span>
</div>
<div>
Average:
<span id="avg"></span>
</div>
Похожие вопросы
Новые вопросы
javascript
По вопросам программирования на ECMAScript (JavaScript / JS) и его различных диалектах / реализациях (кроме ActionScript). Включите все соответствующие теги в свой вопрос; например, [node.js], [jquery], [json] и т. д.