我们常常会遇到计算一系列数据的标准差的问题。最直接的方法是根据公式
进行计算。第一步先计算所有数据的平均值,然后再计算标准差。这个方法需要读取原始数据两次,对于某些情况是不可行的。例如,新的数据在不断的产生,历史数据太多不可能再次读取。这种类型的数据被称为流数据。我们日常生活中的有很多流数据的例子,如股票交易所的股票价格信息,环境温度的监测数据,电信部门的通话记录,网站的点击数据,传感器网络中的监测数据以及网络流量信息等。
网络流量示意图
对这样的数据进行标准差统计,不能采用需要两次读取原始数据的方法。下面的公式只需要读取原始数据一次,因此也被称为在线算法(on-line algorithm)via。
更进一步,我们可用如下的算法得到标准差σ的值:
*Donald E. Knuth (1998). The Art of Computer Programming, volume 2: Seminumerical Algorithms, 3rd edn., p. 232. Boston: Addison-Wesley.
================
本题要求你实现上文最后提到的计算流数据标准差的方法。
输入:
原始的数据,预先不知道个数,double类型。
输出:
输入结束时输出读到的所有数据的标准差,请使用格式化字符串"%8.5f\n"进行输出。
样例输入:
658.19351□346.61608↵
104.76351□975.13757↵
665.75218↵
样例输出:
333.70903↵
import java.util.List;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
List<Double> dataDealList = new ArrayList<Double>();
while(!StdIn.isEmpty()){
dataDealList.add(StdIn.readDouble());
}
//从输入中对应公式参数
double mk = dataDealList.get(0);
double sk = 0.00;
double k = 1.00;
for(int i=1;i<dataDealList.size();i++){
k++;
sk = sk+((k-1)/k)*(dataDealList.get(i)-mk)*(dataDealList.get(i)-mk);
mk = mk +(dataDealList.get(i)-mk)/k;
}
double result = Math.sqrt(sk/(k-1));
StdOut.printf("%8.5f\n", result);
}
}