java实现样本方差的计算

转载自:http://my.oschina.net/BreathL/blog/41063

在一些统计或者排序的算法中,常常要用到样本方差这个东西,来判断一组数据的离散程度。

这是样本方差的公式

s^2=\frac{\sum(X_i-\bar X)^2}{N-1}

      然而,在计算机编程中,往往需要计算运行方差(running variance),因为样本的个数总是的在不断变化的,确切将是不断递增;如果每次增加,都要重新计算平均值,再按次公式,计算出方差;虽可以实现,但计算量会随着数据的增长变的太大。

      因此,递推的公式就显得格外重要;通过n-1个样本时的方差值,和新增的样本,就能得到此时这N个样本的方差;这样计算量不会变同时保持在一个很小的值,可大大提高程序的计算效率。递推公式如下:

      Mn = Mn-1+ (xn - Mn-1)/n 

      Sn = Sn-1 + (xn - Mn-1)*(xn - Mn)

      Mn为平均值,初始时: M1 = x1,  S1 = 0 (此等式的推导证明,我后面给出),而样本方差 s =Sn/(n - 1)

      下面是我自己给出的简单实现(若有更好的实现,请不吝赐教)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package com.mycode.math;
 
public final class RunningVariance {
     private int count; // 样本的个数
     private double mk; // 平均值
     private double sk; // Sn
     private double runVar; // 样本方差
 
     public RunningVariance() {
         this ( 0 , 0.0 , 0.0 );
     }
 
     public RunningVariance( int count, double mk, double sk) {
         this .count = count;
         this .mk = mk;
         this .sk = sk;
         recomputeRunVar();
     }
 
     public double getMk() {
         return mk;
     }
 
     public double getSk() {
         return sk;
     }
 
     /**
      * 获取运行时样本方差
      *
      * @return
      */
     public synchronized double getRunningVariance() {
         return runVar;
     }
 
     /**
      * 增加样本
      *
      * @param sample
      */
     public synchronized void addSample( double sample) {
         if (++count == 1 ) {
             mk = sample;
             sk = 0.0 ;
         } else {
             double oldmk = mk;
             double diff = sample - oldmk;
             mk += diff / count;
             sk += diff * (sample - mk);
         }
         recomputeRunVar();
     }
 
     /**
      * 移除样本
      *
      * @param sample
      */
     public synchronized void removeSample( double sample) {
         int oldCount = getCount();
         double oldmk = mk;
         if (oldCount == 0 ) {
             throw new IllegalStateException();
         }
         if (--count == 0 ) {
             mk = Double.NaN;
             sk = Double.NaN;
         } else {
             mk = (oldCount * oldmk - sample) / (oldCount - 1 );
             sk -= (sample - mk) * (sample - oldmk);
         }
         recomputeRunVar();
     }
 
     private synchronized void recomputeRunVar() {
         int count = getCount();
         runVar = count > 1 ? sk / (count - 1 ) : Double.NaN;
         // 若需要计算标准差
         // runVar = count > 1 ? Math.sqrt(sk / (count - 1)) : Double.NaN;
     }
 
     public synchronized int getCount() {
         return count;
     }
}

         对于递推公式  Sn = Sn-1 + (xn - Mn-1)*(xn - Mn),我自己做了个简单的推导证明,如下图:

        另:图中所提的 等式1  即是 平均数的递推公式:Mn = Mn-1+ (xn - Mn-1)/n 

FFmpeg是一款功能强大的开源多媒体处理工具,广泛应用于视频和音频的编码、解码、转换以及流媒体处理。然而,由于历史原因和标准限制,原生的FFmpeg并不支持将H.265(高效视频编码)格式的视频流封装到FLV(Flash Video)容器中。FLV是一种常见的网络流媒体传输格式,但其最初设计时并未考虑现代高效的H.265编码标准。因此,当尝试将H.265编码的视频与FLV容器结合时,会出现“Video codec hevc not compatible with flv”的错误提示,表明FFmpeg无法识别这种组合。 为了解决这一问题,开发者通常需要对FFmpeg的源代码进行修改和扩展。一个名为“用于解决ffmpeg不支持flv+h265需要修改的文件.zip”的压缩包中包含了一些源代码文件,这些文件旨在扩展FFmpeg的功能,使其能够处理FLV容器中的H.265编码内容。压缩包中的三个关键文件分别是“flvdec.c”“flvenc.c”和“flv.h”,它们分别对应FLV的解码器、编码器和头文件。 flvdec.c:这是FFmpeg的FLV解码器源代码,经过修改后可能支持读取和解析包含H.265数据的FLV流。解码器的作用是从FLV容器中提取视频数据,并将其转换为可处理的原始像素格式。 flvenc.c:这个文件包含FLV编码器的源代码,经过调整后可能允许将H.265编码的视频流封装到FLV容器中。编码器负责将原始视频数据编码为H.265格式,并将其打包到FLV文件中。 flv.h:这是一个头文件,定义了FLV格式相关的常量、结构体和函数原型。修改该文件可能涉及添加或更新与H.265支持相关的定义和接口。 要应用这些修改,开发者需要重新编译FFmpeg源代码,并将修改后的版本替换原有的FFmpeg安装。这样,用户就可以使用定制版的FFmpeg来处理FLV+H.265的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值