0

@ジェリーコフィン

ロジックを取得しますが、while(File >> value)//ファイルから取得した入力が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を使用しています入力ファイルの内容です

4

6 に答える 6

4

悲しいことに、(少なくとも) 3 つの回答があなたを引用していますwhile (!File.eof())が、これは明らかに間違っているという事実についてはコメントしていません。あなたが望むのは次のようなものです:

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

使用によるバグwhile (!File.eof())は潜行性です。通常、妥当に見える結果が得られ、実際にはかなり正しい結果が得られます。問題はeof()、ファイルからの読み取りを試行してから読み取りが失敗するまで true にならないことです。失敗した場合valueでも、最後に読み取った値が保持されるため、リストの最後の数字が実際に 2 回存在したかのように動作します (たとえば、ファイルに 21 個の数字が含まれている場合、ループは 22 回実行され、22 回実行されます)。 2回目の反復では、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

クロスチェックとして、次の 2 つのデータ セットを使用して、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 が生成するものと一致することに注意してください。関数 usingwhile (!file.eof())は、Excel が生成するものと一致し、最後の数値が複製されます。

何が起こってループが 1 回だけ実行され、誤った値が読み取られるのかを推測することさえできません。問題を推測したり再現したりすることができないため、修正方法について有益な提案を行うことはできません。

于 2011-01-25T06:49:26.183 に答える
1

分散の計算は完全に間違っています。統計用語では、分散は

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

そのため、その 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

2 番目の!File.eof()ループでは、ファイルから読み取っていません。分散は、値と平均の差の 2 乗の合計ではありませんか? あなたのループは、ファイルの値をまったく見ていません。また、合計、平均、および分散に整数変数を使用すると、不正確になる可能性があります。double代わりにそれらが必要になる場合があります。

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

上記の行はあまり意味がないようです。そのwhileブロックでは何も読んでいません。この while ブロックが終了することは想定されていません。

于 2011-01-25T05:22:19.670 に答える
0

さて、質問が使用できるライブラリを制限しない場合は、 このタイプのことを簡単にするBoost Accumulatorを使用することをお勧めします.

分散、平均、および必要なその他の基本的な統計値が得られます。での作業にいくつか問題がありlong doubleますが、それ以外は素晴らしいです!

于 2011-01-25T13:44:52.403 に答える