簡體   English   中英

算法-查找循環緩沖區中數字的平均值?

[英]Algorithm — Finding the average of numbers in a circular buffer?

我試圖考慮一種算法來跟蹤循環緩沖區中數字的平均值,假設隨着緩沖區接近容量,數字將被覆蓋。

e.g. size = 4 
[1,2,7,3] => avg = 13/4 = 3.25
add(5)
[5,2,7,3] => avg = 17/4 = 4.25

這是我目前的方法。

class CircularBuffer {

    int[] buffer;  
    int head;
    int tail;
    int sum;

    public CircularBuffer(int n) {   
        tail = 0;
        head = 0;
        buffer = new int[n];
    }

    void addNumber(int number) {  
        if (head == tail - 1) {
            sum -= buffer[tail - 1];
        } else if (head != tail - 1) {
            buffer[head++]= number;
            sum += number;
        }

        head = head % buffer.length;                 
    }

    double avg() {        
        if (head > vtail) {
            return sum / (head - tail + 1);
        } else { 
            return sum / buffer.length;
        }
    }

    public static void main(String[] args) {
        CircularBuffer buf = new CircularBuffer(3);
        buf.addNumber(1);
        buf.addNumber(2);
        buf.addNumber(3);
        buf.addNumber(4);
        System.out.println("Avg"+ buf.avg());                     
    }

不起作用:當前返回5而不是3。

您實際上不需要尾巴,只需要知道是否達到緩沖區的長度即可,因此代碼如下所示:

class CircularBuffer {

    int tail = 0;
    int head = 0;
    int[] buffer;
    int sum = 0;

    public CircularBuffer(int n) {
        buffer = new int[n];
    }

    void addNumber(int number) {
        sum -= buffer[head];
        sum += number;
        buffer[head++] = number;
        head = head % buffer.length;
        if (tail <= buffer.length) {
            tail++;
        }
    }

    double avg() {
        if (head == tail) {
            return (double) sum / (double) head;
        } else {
            return (double) sum / (double) buffer.length;
        }
    }

    public static void main(String[] args) {

        CircularBuffer buf = new CircularBuffer(3);
        buf.addNumber(1);
        buf.addNumber(2);
        buf.addNumber(3);
        buf.addNumber(4);
        System.out.println("Avg" + buf.avg());
    }
}

由於buffer = new int[n]; 用零填充緩沖區,方法addnumber中不需要任何if / else,只需減去之前的值並添加當前值即可。 希望清楚。

為什么只將平均代碼與添加代碼分開?

然后,您只需要遍歷數組,將其求和並除以長度即可。

addNumber方法似乎無法正常工作。

首先,如果要測試緩沖區是否已滿,還需要考慮以下情況: head==length-1 && tail==0 ,而不是簡單的head == tail -1

其次,如果緩沖區已滿,則需要同時增加頭和尾。 而且您可以使用head = (head+1)%length來代替簡單的head++ ,因為head可能是length-1 尾巴也一樣。 另外,在這種情況下,您忘記將數字添加到總和中,以及實際上將數字插入到支持數組中。

我對您的代碼做了一些修改。 這是主要方法,基於您在問題中鍵入的內容。

public static void main(String[] args) {

    CircularBuffer buf = new CircularBuffer(4);
    buf.addNumber(1);
    buf.addNumber(2);
    buf.addNumber(7);
    buf.addNumber(3);
    System.out.println("Avg " + buf.avg());
    buf.addNumber(5);
    System.out.println("Avg " + buf.avg());
}

這是我運行代碼的結果。

Avg 3.25
Avg 4.25

這是我所做的更改,以使您的代碼先進行編譯,然后正確執行。

  1. 我添加了一個類聲明,並使所有變量成為類變量。

  2. 不需要head變量。 總是零位。

  3. 我添加了一個布爾值,讓我知道循環緩沖區中的值何時被覆蓋。

  4. 我在構造函數中初始化了sum和布爾變量bufferFull。

  5. 我重寫了addNumber方法,以便總和始終包含正確的值。

  6. 由於sum始終具有正確的值,因此avg方法僅計算平均值。

  7. 我格式化了Java代碼,以便其他人更容易閱讀。

這是修改后的代碼。

package com.ggl.testing;

public class CircularBuffer {

    private boolean bufferFull;

    private int tail;
    private int sum;

    private int[] buffer;

    public CircularBuffer(int n) {
        this.bufferFull = false;
        this.tail = 0;
        this.sum = 0;
        this.buffer = new int[n];
    }

    public void addNumber(int number) {

        sum += number;
        if (bufferFull) {
            sum -= buffer[tail];
        }

        buffer[tail] = number;
        tail++;

        if (tail >= buffer.length) {
            tail = tail % buffer.length;
            bufferFull = true;
        }
    }

    public double avg() {

        int length = tail;
        if (bufferFull) {
            length = buffer.length;
        }
        return (double) sum / length;

    }

    public static void main(String[] args) {

        CircularBuffer buf = new CircularBuffer(4);
        buf.addNumber(1);
        buf.addNumber(2);
        buf.addNumber(7);
        buf.addNumber(3);
        System.out.println("Avg " + buf.avg());
        buf.addNumber(5);
        System.out.println("Avg " + buf.avg());
    }
} 

希望您能理解我的所作所為,並可以將這些原則應用於下一個任務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM