C# 中的简单循环(移动平均)数组

发布于 2024-09-06 19:04:58 字数 464 浏览 13 评论 0原文

作为诊断,我想在我的应用程序中显示每秒的周期数。 (想想第一人称射击游戏中的每秒帧数。)

但我不想显示最新值或自启动以来的平均值。我想要计算的是最后一个 X 值的平均值。

我想我的问题是存储这些值的最佳方式。我的第一个想法是创建一个固定大小的数组,这样每个新值都会推出最旧的值。这是最好的方法吗?如果是这样,我将如何实施?

编辑: 这是我编写的类:RRQueue。它继承了 Queue,但会强制执行容量并在必要时出列。

编辑2: Pastebin已经过时了。现在位于GitHub 存储库

As a diagnostic, I want to display the number of cycles per second in my app. (Think frames-per-second in a first-person-shooter.)

But I don't want to display the most recent value, or the average since launch. What I want to calculate is the mean of the last X values.

My question is, I suppose, about the best way to store these values. My first thought was to create a fixed size array, so each new value would push out the oldest. Is this the best way to do it? If so, how would I implement it?

EDIT:
Here's the class I wrote: RRQueue. It inherits Queue, but enforces the capacity and dequeues if necessary.

EDIT 2:
Pastebin is so passé. Now on a GitHub repo.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

紫轩蝶泪 2024-09-13 19:04:59

最简单的选择可能是使用 Queue,因为这提供了您所追求的先进先出行为。只需 Enqueue() 您的项目,并且当您有超过 X 个项目时, Dequeue() 额外的项目。

The easiest option for this is probably to use a Queue<T>, as this provides the first-in, first-out behavior you're after. Just Enqueue() your items, and when you have more than X items, Dequeue() the extra item(s).

逆夏时光 2024-09-13 19:04:59

一个简单但快速的实现:

private int[] values = new int [10];  // all 0's initially
private int sum = 0;
private int pos = 0;

public void AddValue (int v)
{
   sum -= values[pos];  // only need the array to subtract old value
   sum += v;
   values[pos] = v;     
   pos = (pos + 1) % values.Length;    
}

public int Average => sum / values.Length;

A simple but fast implementation:

private int[] values = new int [10];  // all 0's initially
private int sum = 0;
private int pos = 0;

public void AddValue (int v)
{
   sum -= values[pos];  // only need the array to subtract old value
   sum += v;
   values[pos] = v;     
   pos = (pos + 1) % values.Length;    
}

public int Average => sum / values.Length;
世界如花海般美丽 2024-09-13 19:04:59

可能使用过滤器:

平均值 = 0.9*平均值 + 0.1*值
其中“值”是最近的测量值

随 0.9 和 0.1 的变化而变化(只要这两者之和为 1)

这并不完全是平均值,但它确实过滤掉尖峰、瞬态等,但不需要数组用于存储。

问候,
卡雷尔

Possibly use a filter:

average = 0.9*average + 0.1*value
where 'value' is the most recent measurement

Vary with the 0.9 and 0.1 (as long as the sum of these two is 1)

This is not exactly an average, but it does filter out spikes, transients, etc, but does not require arrays for storage.

Greetings,
Karel

梦里°也失望 2024-09-13 19:04:59

如果您需要最快的实现,那么是的,具有单独计数的固定大小数组 () 将会是最快的。

If you need the fastest implementation, then yes, a fixed-size array ()with a separate count would be fastest.

剑心龙吟 2024-09-13 19:04:59

您应该看一下 Windows 内置的性能监控:D。

MSDN< /a>

如果您之前没有使用过该 API,您可能会觉得有点奇怪,但它快速、强大、可扩展,并且可以快速获得可用的结果。

You should take a look at the performance monitoring built into Windows :D.

MSDN

The API will feel a bit wonky if you haven't played with it before, but it's fast, powerful, extensible, and it makes quick work of getting usable results.

你好,陌生人 2024-09-13 19:04:59

我的实现:

class RoundRobinAverage
{
    int[] buffer;
    byte _size;
    byte _idx = 0;
    public RoundRobinAverage(byte size)
    {
        _size = size;
        buffer = new int[size];
    }

    public double Calc(int probeValue)
    {
        buffer[_idx++] = probeValue;
        if (_idx >= _size)
            _idx = 0;

        return buffer.Sum() / _size;
    }
}

用法:

private RoundRobinAverage avg = new RoundRobinAverage(10);\
...
var average = avg.Calc(123);

my implementation:

class RoundRobinAverage
{
    int[] buffer;
    byte _size;
    byte _idx = 0;
    public RoundRobinAverage(byte size)
    {
        _size = size;
        buffer = new int[size];
    }

    public double Calc(int probeValue)
    {
        buffer[_idx++] = probeValue;
        if (_idx >= _size)
            _idx = 0;

        return buffer.Sum() / _size;
    }
}

usage:

private RoundRobinAverage avg = new RoundRobinAverage(10);\
...
var average = avg.Calc(123);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文