1. 程式人生 > >java 求標準差程式碼實現

java 求標準差程式碼實現

package com.qingyuan.huake;

/**
 * reference: <[http://my.oschina.net/BreathL/blog/41063]>
 * 對樣本進行統計, 計算樣本的方差&標準差
 * Sn = Sn-1 + (xn - Mn-1)*(xn - Mn)
 * Mn = Mn-1+ (xn - Mn-1)/n
 */
public final class StandardDeviation
{
    /** 樣本的個數*/
    private int count; 
    
    /** 平均值*/
    private double averageVar;
    
    /** sn樣本方差*/
    private double standardDeviationSum;
    
    /** 樣本標準差*/
    private double standard_Deviation;
    
    public StandardDeviation()
    {
        this(0, 0.0, 0.0);
    }

    public StandardDeviation(int count, double standardDeviationSum, double averageVar)
    {
        this.count = count;
        this.standardDeviationSum = standardDeviationSum;
        this.averageVar = averageVar;
        recomputerstandard_Deviation();
    }

    public synchronized int getCount()
    {
        return count;
    }
    
    private void recomputerstandard_Deviation()
    {
        int count = getCount();
        standard_Deviation = count > 1 ? Math.sqrt(standardDeviationSum / (count -1)) : Double.NaN;
    } 
    
    /**
     *  獲取執行時樣本的方差
     *  @return double
     */
    public synchronized double getRunningVariance()
    {
        return standard_Deviation;
    }
    
    /**
     * 增加一個樣本時重新計算
     * @param sample void
     */
    public synchronized void addSample(double sample)
    {
        if (++count == 1)
        {
            averageVar = sample;
            standardDeviationSum = 0.0;
        }
        else
        {
            double oldaverageVar = averageVar;
            double diff = sample - oldaverageVar;
            averageVar += diff / count;
            standardDeviationSum += diff * (sample - averageVar);
        }

        recomputerstandard_Deviation();
    }
    
    /**
     * 移除一個樣本時重新計算
     * @param sample void
     */
    public synchronized void removeSample(double sample)
    {
        int oldCount = getCount();
        double oldaverageVar = averageVar;
        
        if (oldCount == 0)
        {
            throw new IllegalStateException();
        }
        
        if (--count == 0)
        {
            averageVar = Double.NaN;
            standardDeviationSum = Double.NaN;
        }
        else
        {
            averageVar = (oldCount * oldaverageVar - sample) / (oldCount - 1);
            standardDeviationSum = (sample - averageVar) * (sample - oldaverageVar);
        }
        
        recomputerstandard_Deviation();
    }
    
}

package com.qingyuan.huake;

import static org.junit.Assert.assertEquals;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import org.junit.Test;

public class TestSD
{
    @Test
    public void test()
    {
        StandardDeviation s = new StandardDeviation();
        
        int[] arr = {2, 4, 4, 5, 5, 6, 2, 3, 3, 6};
        int sum = 0, average =0 ;
        double sn  = 0.0;
        double standardDeviation = 0.0;
         
        for (int i = 0, len = arr.length; i < len; i++)
        {
            sum = sum + arr[i];
            s.addSample(arr[i]);
        }
        
        average = sum / 10;
        System.out.println("average value is = " + average);
        
        for (int j = 0, len = arr.length; j < len; j++)
        {
            sn = sn + Math.pow((arr[j] - average), 2);
        }
             
        // 測試資料計算
        standardDeviation = Math.sqrt(sn / arr.length);
        System.out.println(standardDeviation);
        
        // 通過函式計算
        double result = s.getRunningVariance();
        System.out.println(result);
        
        // 擷取小數點後兩位判斷是否相等
        NumberFormat formatter = new DecimalFormat("#0.");
        String res = formatter.format(result);
        String std = formatter.format(standardDeviation);
        
        assertEquals(std, res);
    }
	
}