java中有没有获取移动平均线的函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3793400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:01:54  来源:igfitidea点击:

Is there a function in java to get moving average

java

提问by chai

I have a situation where I need to process 5000 samples from a device in every 0.5 sec.

我有一种情况,我需要在每 0.5 秒内处理来自设备的 5000 个样本。

Lets say the window size is 100, then there would be 50 points resulting from the moving average. I am trying with conventional method, i.e. with loops. But this is a very inefficient way to do it. Any suggestions ?

假设窗口大小为 100,则移动平均线将产生 50 个点。我正在尝试使用传统方法,即循环。但这是一种非常低效的方法。有什么建议 ?

回答by Thomas Mueller

You can do that in O(1): keep a queue of the last 50 entries. When you add an entry and the queue is shorter 50 elements, just update the total and the count. If it is longer than 50 elements, update the total and the count as well. Pseudocode:

您可以在 O(1) 中做到这一点:保留最后 50 个条目的队列。当您添加一个条目并且队列较短 50 个元素时,只需更新总数和计数。如果它超过 50 个元素,也更新总数和计数。伪代码:

add(double x) {
    total += x;
    addToQueue(x);
    if (queueSize > 50) {
        total -= removeLastFromQueue();
    } else {
        count++;
    }
}
double getAverage() {
    return total / count;
}

回答by Brian Agnew

Check out the Apache Mathslibrary. This has methods for doing precisely what you want. See DescriptiveStatisticsand Meanfor more info.

查看Apache 数学库。这有一些方法可以准确地做你想做的事。有关详细信息,请参阅DescriptiveStatisticsMean

回答by Tony Ennis

Here's one way.

这是一种方法。

public class Rolling {

    private int size;
    private double total = 0d;
    private int index = 0;
    private double samples[];

    public Rolling(int size) {
        this.size = size;
        samples = new double[size];
        for (int i = 0; i < size; i++) samples[i] = 0d;
    }

    public void add(double x) {
        total -= samples[index];
        samples[index] = x;
        total += x;
        if (++index == size) index = 0; // cheaper than modulus
    }

    public double getAverage() {
        return total / size;
    }   
}


public class RollingTest extends TestCase {

    private final static int SIZE = 5;
    private static final double FULL_SUM = 12.5d;

    private Rolling r;

    public void setUp() {
        r = new Rolling(SIZE);
    }

    public void testInitial() {
        assertEquals(0d, r.getAverage());
    }

    public void testOne() {
        r.add(3.5d);
        assertEquals(3.5d / SIZE, r.getAverage());
    }

    public void testFillBuffer() {
        fillBufferAndTest();
    }

    public void testForceOverWrite() {
        fillBufferAndTest();

        double newVal = SIZE + .5d;
        r.add(newVal);
        // get the 'full sum' from fillBufferAndTest(), add the value we just added,
        // and subtract off the value we anticipate overwriting.
        assertEquals((FULL_SUM + newVal - .5d) / SIZE, r.getAverage());
    }

    public void testManyValues() {
        for (int i = 0; i < 1003; i++) r.add((double) i);
        fillBufferAndTest();
    }


    private void fillBufferAndTest() {
        // Don't write a zero value so we don't confuse an initialized
        // buffer element with a data element.
        for (int i = 0; i < SIZE; i++) r.add(i + .5d);
        assertEquals(FULL_SUM / SIZE, r.getAverage());
    }
}

回答by Daniel Alexiuc

Here's a good implementation, using BigDecimal:

这是一个很好的实现,使用 BigDecimal:

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.LinkedList;
import java.util.Queue;

public class MovingAverage {

    private final Queue<BigDecimal> window = new LinkedList<BigDecimal>();
    private final int period;
    private BigDecimal sum = BigDecimal.ZERO;

    public MovingAverage(int period) {
        assert period > 0 : "Period must be a positive integer";
        this.period = period;
    }

    public void add(BigDecimal num) {
        sum = sum.add(num);
        window.add(num);
        if (window.size() > period) {
            sum = sum.subtract(window.remove());
        }
    }

    public BigDecimal getAverage() {
        if (window.isEmpty()) return BigDecimal.ZERO; // technically the average is undefined
        BigDecimal divisor = BigDecimal.valueOf(window.size());
        return sum.divide(divisor, 2, RoundingMode.HALF_UP);
    }
}

回答by mylittleswift

As far as I know, there is no such function (class) in Java. But you can make one by yourself. Here is a simple example (SMA-Simple Moving Average):

据我所知,Java 中没有这样的函数(类)。但是你可以自己制作一个。这是一个简单的例子(SMA-简单移动平均线):

public class MovingAverage {
    private int [] window;
    private int n, insert;
    private long sum;

    public MovingAverage(int size) {
        window = new int[size];
        insert = 0;
        sum = 0;
    }

    public double next(int val) {
        if (n < window.length)  n++;
        sum -= window[insert];
        sum += val;
        window[insert] = val;
        insert = (insert + 1) % window.length;
        return (double)sum / n;
    }
}

回答by vimal aditya

static int[] myIntArray = new int[16];
public static double maf(double number)
{
    double avgnumber=0;
    for(int i=0; i<15; i++)
    {
        myIntArray[i] = myIntArray[i+1];
    }
    myIntArray[15]= (int) number;
    /* Doing Average */
    for(int  i=0; i<16; i++)
    {
        avgnumber=avgnumber+ myIntArray[i];
    }
    return avgnumber/16;

}

this algorithm can also be called as Moving Average Filter which is working well for me ... i implemented this algo in my graph project!

这个算法也可以称为移动平均滤波器,它对我来说效果很好......我在我的图形项目中实现了这个算法!

回答by Zaheer

Java 8 has added java.util.IntSummaryStatistics. There similar classes for Doubleand Longas well. Fairly straightforward to use:

Java 8 增加了java.util.IntSummaryStatistics. 有类似的课程Double,并Long为好。使用起来相当简单:

IntSummaryStatistics stats = new IntSummaryStatistics();
stats.accept(1);
stats.accept(3);
stats.getAverage(); // Returns 2.0