Created
April 17, 2019 08:27
-
-
Save imvenj/0700741bdf6f5decdbd57365e1caf806 to your computer and use it in GitHub Desktop.
SMA implementation in simple function form, or in class form.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Simple move average | |
function sma(data, dataLength, sampleRate=250, frequency=50) { | |
if (data.length === 0) return data; | |
const filterTL = Math.round(sampleRate / frequency) | |
const filteredData = [] | |
if (filterTL > dataLength) { | |
throw new Error('Data length is not enough.') | |
} | |
else { | |
for (let i = 0; i < dataLength; ++i) { | |
if (i <= dataLength - filterTL) { | |
let sum = 0 | |
for (let j = i; j < i + filterTL; ++j) { | |
sum += data[j] | |
} | |
const average = sum / filterTL | |
filteredData.push(average) | |
} | |
else { | |
filteredData.push(0) // Not necessary, maybe. | |
} | |
} | |
return filteredData | |
} | |
} | |
class SMACalculator { | |
constructor(sampleRate = 250, frequency = 50) { | |
this.container = [] | |
this.sampleRate = sampleRate | |
this.frequency = frequency | |
this.batchSize = Math.round(sampleRate / frequency) | |
this.lastValue = null | |
this.sum = null | |
} | |
update(newData = []) { | |
console.log(`this.container length: ${this.container.length}`, this.container) | |
const tempArray = this.container.concat(newData) | |
const dataLength = tempArray.length | |
const maxMoveIndex = dataLength - this.batchSize | |
console.log(`maxMoveIndex: ${maxMoveIndex}`) | |
// 如果传入的数组成员数不足,则存入容器,返回空数组 | |
if (dataLength < this.batchSize) { | |
this.container = tempArray | |
return [] | |
} | |
// 开始移动。 | |
const result = [] | |
this.container = [] // 清空缓存 | |
for (let i = 0; i < dataLength; ++i) { | |
// 计算移动平均值 | |
if (i <= maxMoveIndex) { | |
// 计算 sum。 | |
if (this.sum === null) { // 第一次进入,先算出 sum 的初始值 | |
for (let j = 0; j < this.batchSize; ++j) { | |
this.sum += tempArray[j] | |
} | |
} | |
else { | |
// 非第一轮运算时,当 i 为 0 时,调用缓存的 lastValue,否则直接用前一个值。 | |
const lastValue = (i === 0) ? this.lastValue : tempArray[i-1] | |
console.log(`lastValue: ${lastValue}`) | |
this.sum = this.sum - lastValue + tempArray[i + this.batchSize - 1] | |
} | |
const average = this.sum / this.batchSize | |
result.push(average) // 推入平均值 | |
// 存下参与计算的最后一个值 | |
if (i === maxMoveIndex) { | |
this.lastValue = tempArray[i] | |
} | |
} | |
else { | |
this.container.push(tempArray[i]) //缓存未参与运算的值 | |
} | |
} | |
return result | |
} | |
reset() { | |
this.container = [] | |
this.lastValue = null | |
this.sum = null | |
} | |
} | |
const orig = [97,72,98,83,71,99,90,28,98,58,49,4,98,78,1,63,85,92,56,96,17,59,38,34,21,97,76,86,87,99,98,2,11,96,91,14,19,19,38] | |
const orig1 = [97,72,98,83,71,99,90,28] | |
const orig2 = [98,58,49,4,98,78,1,63,85,92,56,96] | |
const orig3 = [17,59,38,34,21,97,76,86,87,99,98,2,11,96,91] | |
const orig4 = [14,19,19,38] | |
const calc = new SMACalculator() | |
const result = calc.update(orig) | |
const calc2 = new SMACalculator() | |
const result2 = calc2.update(orig1).concat(calc2.update(orig2)).concat(calc2.update(orig3)).concat(calc2.update(orig4)) | |
console.log(`orig: ${orig.length}`) | |
console.log(`Class: ${result}`, `${result.length}`) | |
console.log(`Class: ${result2}`, `${result2.length}`) | |
console.log(`Function: ${sma(orig, orig.length)}`, `${sma(orig, orig.length).length}`) | |
// const calc = new SMACalculator() | |
// let result = calc.update(orig1) | |
// console.log(`result: ${result.length}`, result) | |
// result = calc.update(orig2) | |
// console.log(`result: ${result.length}`, result) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment