-5

I'm trying to calculate simple MA by reading values from a file.

The values are stored like this:

11
12
13
14
15
16
17

I've did this so far:

for (int i = 0; (ifs); i++) {

        ifs >> price;
        //cout << "price:" << price;
        prices_vec.push_back(price);
        sum += prices_vec[i];
        cnt++;
        if (cnt >= 5) {

            output_file << sum / 5 << endl;
            cout << "Your SMA: " << (sum / 5) << endl;
            sum -= prices_vec[cnt - 5];
        }
    }

This works, but at the end, it adds two additional numbers in the end. The output in file is:

13
14
15
15.8
0

Any idea why this might be happening? And, is there a more efficient way to calculate SMA?

  • 2
    Please show a [MCVE]. – Jabberwocky Sep 11 '18 at 11:38
  • BTW: what's the purpose of `(ifs)` in `for (int i = 0; (ifs); i++)`? The problem is most likely _there_. – Jabberwocky Sep 11 '18 at 11:39
  • 1
    You do not check if `ifs >> price;` works, move this statement into the `for` condition. So `for (int i = 0; (ifs); i++)` should be `for (int i = 0; ifs >> price; i++)` – mch Sep 11 '18 at 11:39
  • I would say the last one is from `output_file << MA << endl;`. – Jarod42 Sep 11 '18 at 11:39
  • 1
    This is closely related to [Why is `iostream::eof` inside a loop condition considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) – molbdnilo Sep 11 '18 at 11:40
  • Hi, ifs is ifstream. – yuckfootwo Sep 11 '18 at 11:41
  • Btw, I suggest to either work with `std::vector`, or use only stream. – Jarod42 Sep 11 '18 at 11:41
  • It does not "add two additional values at the end"... as @mch wrote you do not check if the parsed char is a correct value, it might be a simple endline or end of file... In addition you report an output that is not related to your program since you coded [cout << "Your SMA: " << (sum / 5) << endl;] and I cannot guess why the final output is 0. – giuseppe Sep 11 '18 at 11:47
  • @mch I tried your suggestion, but now code directly jumps to the end of main() – yuckfootwo Sep 11 '18 at 11:48
  • @Jarod42 I've tried using vector, but the code doesn't output first MA at all. I've pasted the code below: – yuckfootwo Sep 11 '18 at 11:48
  • while (ifs >> price) { prices_vec.push_back(price); if (prices_vec.size() == 6) { prices_vec.erase(prices_vec.begin()); double sum = prices_vec[0] + prices_vec[1] + prices_vec[2] + prices_vec[3] + prices_vec[4]; cout << sum; MA = sum / 5; cout << MA << endl; } output_file << MA << endl; } – yuckfootwo Sep 11 '18 at 11:50
  • 1
    I meant, if you work with `std::vector`, you create a first function to create it from stream. (you can then check vector content is what you expect). Then a second function to calculate your moving average. (that you can test independently from file/stream, as you just need a std::vector). – Jarod42 Sep 11 '18 at 11:54
  • there are going to be numerical stability issues with this sort of implementation; given that you're only averaging over 5 samples you could generate the average each time. will only be an issue if numbers have very different scales or you're running on thousands of datapoints – Sam Mason Sep 11 '18 at 13:11

1 Answers1

0

I believe this will solve your problem:

int main()
{
    int cnt = 0, sum = 0;
    vector<float> prices_vec;   
    std::ifstream ifs ("Nos.txt", std::ifstream::in); 
    float price;

    for (int i = 0; (ifs) >> price; i++) {
        prices_vec.push_back(price);
        sum += prices_vec[i];
        cnt++;
        if (cnt >= 5) {

            cout << sum / 5 << endl;
            cout << "Your SMA: " << (sum / 5) << endl;
            sum -= prices_vec[cnt - 5];
        }
    }    
    return 0;
}
P.W
  • 26,289
  • 6
  • 39
  • 76