从文件方差计算中读取

时间:2011-01-25 05:13:50

标签: c++ variance

@Jerry Coffin

我得到逻辑, while(文件>>值)//而刚从文件中获取的输入为true ....做计算。 然而,当我实施这个时,计数器只进入1&它的价值非常高。有时是错的,但我不知道是什么。该文件有效

File.open(FileName, ifstream::in);  
while(File>>value){  
    ++counter;  
    sum += value;  
    sumsqr+= value * value;  
}  
average=sum/counter;  
variance = sumsqr/counter - average*average;  
File.close();  

这是我正在使用“text.txt”的输入文件的内容 23244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 14864152412505862058641048186386848408

6 个答案:

答案 0 :(得分:4)

可悲的是,(至少)有三个答案引用了你的while (!File.eof()),而没有评论这是完全错误的事实。你想要的是这样的:

while (File>>value) {
    ++counter;
    sum += value;
    sumsqr += value * value;
}
average = sum/counter;
variance = sumsqr/counter - average * average;

使用while (!File.eof())的错误是阴险的 - 您通常会得到看起来合理的结果,并且实际上相当接近正确。问题是{I} eof()在您尝试从文件中读取之后才会变为真,并且尝试的读取失败。当它失败时,value仍将具有您读取的最后一个值,因此它的行为就像列表中的最后一个数字确实存在两次(例如,如果您的文件包含21个数字,则您的循环将执行22次,并且在22 nd 迭代中,它将再次使用21 st 数字)。这会使你的计算稍微偏离,但通常不够明显 - 几乎是最糟糕的错误。

编辑:这是一个完整的测试程序:

#include <fstream>
#include <iostream>

double variance(std::istream &File) {
    double value, average, sum, counter, sumsqr, variance;
    while (File>>value) {
        ++counter;
        sum += value;
        sumsqr += value * value;
    }
    average = sum/counter;
    variance = sumsqr/counter - average * average;
    return variance;
}

double variance2(std::istream &File) {
    double value, average, sum, counter, sumsqr, variance;
    while (!File.eof()) {
        ++counter;
        File >> value;
        sum += value;
        sumsqr += value * value;
    }
    average = sum/counter;
    variance = sumsqr/counter - average * average;
    return variance;
}

int main() { 
    std::ifstream in("data.txt");
    double v1 = variance1(in);
    in.clear();
    in.seekg(0);
    double v2 = variance2(in);

    std::cout << "Using \"while (file>>value)\"" << v1 << "\n";
    std::cout << "Using \"while (!file.eof())\"" << v2 << "\n";
    return 0;
}

以下是一些测试数据:

1
2
3
4
5
6
7
8
9
10

当我对这些数据运行时,我得到:

Using "while (file>>value)": 8.25 
Using "while (!file.eof())": 9.17355

作为交叉检查,我使用两组数据在Excel中进行了计算:

1           1
2           2
3           3
4           4
5           5
6           6
7           7
8           8
9           9
10          10
8.25        10
            9.173553719

每列中的最后一行是对前面数据执行“VARP”的公式的结果。请注意,我的函数与Excel为正确的输入数据生成的函数匹配。使用while (!file.eof())的函数与Excel生成的函数匹配,最后一个数字是重复的。

我甚至无法猜测是什么让环路只运行一次而且读取的值不正确。如果不能猜测或重现问题,我恐怕无法提供有关如何解决问题的有用建议。

答案 1 :(得分:1)

您的方差计算完全不正确。在统计学方面,方差是

E(x^2) - [E(x)^2]

所以摆脱第二个循环(我甚至不确定你认为它做了什么)并将第一个循环更改为:

while(!File.eof()){
    counter++;
    value = File.get();
    sum += value;
    sumsqr += value*value;
}
average = sum/counter;
variance = (sumsqr/counter) - (average*average);

编辑:Jerry Coffin的answer甚至更好,因为它展示了eof()的问题。

答案 2 :(得分:0)

你可以写那样的

variance=counter*(average*average)

答案 3 :(得分:0)

在第二个!File.eof()循环中,您没有从文件中读取。方差不是值与平均值之差的平方和吗?您的循环根本不会查看文件中的值。此外,使用整数变量求和,平均值和方差可能会导致不准确;你可能想要double代替那些人。

答案 4 :(得分:0)

while(!File.eof()){
        variance +=(average*average);
    }

以上几行似乎没有多大意义。你不是在读那块东西时读的东西。这个while块不会终止。

答案 5 :(得分:0)

好吧,如果问题没有限制你可以使用哪些库我建议使用Boost Accumulators使这类事情变得微不足道。

你得到方差,均值,以及你想要的任何其他基本统计值。他们在使用long double时遇到了一些问题,但是他们很棒!