blockchain/internal/lib/strategy/ring_queue.go

56 lines
1.5 KiB
Go
Raw Normal View History

2025-08-14 23:41:29 +00:00
package strategy
import (
"container/list"
"github.com/shopspring/decimal"
)
/************** 基礎的固定長度隊列,用來計算移動平均 **************/
2025-08-15 01:36:36 +00:00
// 請注意: 目前為非併發版本,使用場警還不需要
2025-08-14 23:41:29 +00:00
type ringQD struct {
2025-08-15 01:36:36 +00:00
N uint // 窗口大小(需要保留的資料數量)需要保留的數量沒有負數
2025-08-14 23:41:29 +00:00
l *list.List // 用於儲存資料的雙向鏈表
sum decimal.Decimal // 當前窗口的總和,方便快速計算平均值
}
// 建立一個固定長度的隊列
2025-08-15 01:36:36 +00:00
func newRingQD(n uint) *ringQD {
2025-08-14 23:41:29 +00:00
return &ringQD{N: n, l: list.New(), sum: decimal.Zero}
}
// push將新的數值放入隊列並維護總和
func (q *ringQD) push(x decimal.Decimal) {
q.l.PushBack(x)
q.sum = q.sum.Add(x)
// 如果超出最大長度,移除最舊的數值
2025-08-15 01:36:36 +00:00
if uint(q.l.Len()) > q.N {
2025-08-14 23:41:29 +00:00
f := q.l.Front()
q.sum = q.sum.Sub(f.Value.(decimal.Decimal))
q.l.Remove(f)
}
}
// ready判斷隊列是否已經填滿
2025-08-15 01:36:36 +00:00
func (q *ringQD) ready() bool { return q.N > 0 && uint(q.l.Len()) == q.N }
2025-08-14 23:41:29 +00:00
// mean計算平均值
func (q *ringQD) mean() decimal.Decimal {
if q.l.Len() == 0 {
return decimal.Zero
}
2025-08-15 01:36:36 +00:00
2025-08-14 23:41:29 +00:00
return q.sum.Div(decimal.NewFromInt(int64(q.l.Len())))
}
// values返回隊列中所有的值複製一份不影響原資料
func (q *ringQD) values() []decimal.Decimal {
out := make([]decimal.Decimal, 0, q.l.Len())
for e := q.l.Front(); e != nil; e = e.Next() {
out = append(out, e.Value.(decimal.Decimal))
}
2025-08-15 01:36:36 +00:00
2025-08-14 23:41:29 +00:00
return out
}