0

@杰里棺材

我明白了逻辑,while(File>>value)//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();  

here's the contents of the input file I am using "text.txt" 23244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 1486415241250586205864104818638684840823244564 14864152412505862058641048186386848408

4

6 回答 6

4

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

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

使用的错误while (!File.eof())是阴险的——你通常会得到看起来合理的结果,实际上非常接近正确。问题是eof()直到您尝试从文件中读取并且尝试读取失败之后才会成为真的。当它失败时,value仍然会有你读取的最后一个值,所以它会像列表中的最后一个数字确实存在两次(例如,如果你的文件包含 21 个数字,你的循环将执行 22 次,并且在 22 nd迭代,它将再次使用第 21数字)。这会让你的计算有点偏离,但通常还不够,以至于它立即显而易见——几乎是最糟糕的一种错误。

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

#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 生成的最后一个数字重复的函数相匹配。

我什至无法开始猜测发生了什么使循环只运行一次并读取了不正确的值。由于无法猜测或重现问题,恐怕我无法提供有关如何解决问题的有用建议。

于 2011-01-25T06:49:26.183 回答
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 的回答更好,因为它证明了eof().

于 2011-01-25T05:25:09.933 回答
0

你可以这样写

variance=counter*(average*average)
于 2011-01-25T05:20:27.877 回答
0

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

于 2011-01-25T05:20:33.117 回答
0
while(!File.eof()){
        variance +=(average*average);
    }

以上几行似乎没有多大意义。您没有在该 while 块中阅读任何内容。这个 while 块预计不会终止。

于 2011-01-25T05:22:19.670 回答
0

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

您将获得方差、均值以及您想要的任何其他基本统计值。他们在使用 时遇到了一些问题long double,但除此之外它们都很棒!

于 2011-01-25T13:44:52.403 回答