17

I have this code, which reads in input from a file and stores it in a vector. So far, I've gotten it to give me the sum of the values within the vector and give the mean of the values using the sum.

What I'd like to do now is learn how to access the vector again and subtract a value from each element of the vector and then print it out again. For example, once the sum and mean are calculated, I'd like to be able to reprint each value in the terminal minus the mean. Any suggestions/examples?

#include <iostream>
#include <vector>
#include <fstream>
#include <cmath>

using namespace std;

int main()
{
    fstream input;
    input.open("input.txt");
    double d;
    vector<double> v;
    cout << "The values in the file input.txt are: " << endl;
    while (input >> d)
    {
        cout << d << endl;
        v.push_back(d);
    }

double total = 0.0;
double mean = 0.0;
double sub = 0.0;
for (int i = 0; i < v.size(); i++)
{
    total += v[i];
    mean = total / v.size();
    sub = v[i] -= mean;
}
cout << "The sum of the values is: " << total << endl;
cout << "The mean value is: " << mean << endl;
cout << sub << endl;
}
UndefinedReference
  • 1,223
  • 4
  • 22
  • 52
  • 3
    You already write sub = v[i] -= mean. v[i] -= mean is the same as v[i] = v[i] - mean. So you are already modifying the array elements! – mmmmmmmm Jan 26 '11 at 18:48
  • "_Any suggestions/examples?_" Yes, my suggestion is to read a good source of documentation like *cppreference*, which will include plenty of examples for such simple requests, making asking a question on SO not required or useful. – underscore_d Sep 22 '18 at 13:58

7 Answers7

19

You can simply access it like an array i.e. v[i] = v[i] - some_num;

Naveen
  • 74,600
  • 47
  • 176
  • 233
  • I've already tried doing this within my for loop but it only returns the last element in the vector - number. How can I make it go through and do it to all the elements in the vector? – UndefinedReference Jan 26 '11 at 17:33
  • yes, it's just a small change to the last block, I changed it in the code above. – UndefinedReference Jan 26 '11 at 17:52
  • @Meursault: But your loop is wrong, only from the last element the correct mean will be subtracted, from all other elements the subtracted mean will be wrong as your `total` will not be correct. Is that the issue you are facing? – Naveen Jan 26 '11 at 18:43
  • You need two loops: the first one accumulates the sum into "total", then the mean may be calculated (once, not inside the loop), then a second loop in which you subtract the calculated "mean" from each element. – David M. Miller Jan 26 '11 at 19:29
10

Well, you could always run a transform over the vector:

std::transform(v.begin(), v.end(), v.begin(), [mean](int i) -> int { return i - mean; });

You could always also devise an iterator adapter that returns the result of an operation applied to the dereference of its component iterator when it's dereferenced. Then you could just copy the vector to the output stream:

std::copy(adapter(v.begin(), [mean](int i) -> { return i - mean; }), v.end(), std::ostream_iterator<int>(cout, "\n"));

Or, you could use a for loop...but that's kind of boring.

Edward Strange
  • 40,307
  • 7
  • 73
  • 125
3

You can access the values in a vector just as you access any other array.

for (int i = 0; i < v.size(); i++)
{         
  v[i] -= 1;         
} 
Nick Banks
  • 4,298
  • 5
  • 39
  • 65
3

Your code works fine. When I ran it I got the output:

The values in the file input.txt are:
1
2
3
4
5
6
7
8
9
10
The sum of the values is: 55
The mean value is: 5.5

But it could still be improved.

You are iterating over the vector using indexes. This is not the "STL Way" -- you should be using iterators, to wit:

typedef vector<double> doubles;
for( doubles::const_iterator it = v.begin(), it_end = v.end(); it != it_end; ++it )
{
    total += *it;
    mean = total / v.size();
}

This is better for a number of reasons discussed here and elsewhere, but here are two main reasons:

  1. Every container provides the iterator concept. Not every container provides random-access (eg, indexed access).
  2. You can generalize your iteration code.

Point number 2 brings up another way you can improve your code. Another thing about your code that isn't very STL-ish is the use of a hand-written loop. <algorithm>s were designed for this purpose, and the best code is the code you never write. You can use a loop to compute the total and mean of the vector, through the use of an accumulator:

#include <numeric>
#include <functional>
struct my_totals : public std::binary_function<my_totals, double, my_totals>
{
    my_totals() : total_(0), count_(0) {};
    my_totals operator+(double v) const
    {
        my_totals ret = *this;
        ret.total_ += v;
        ++ret.count_;
        return ret;
    }
    double mean() const { return total_/count_; }
    double total_;
    unsigned count_;
};

...and then:

my_totals ttls = std::accumulate(v.begin(), v.end(), my_totals());
cout << "The sum of the values is: " << ttls.total_ << endl;
cout << "The mean value is: " << ttls.mean() << endl;

EDIT:

If you have the benefit of a C++0x-compliant compiler, this can be made even simpler using std::for_each (within #include <algorithm>) and a lambda expression:

double total = 0;
for_each( v.begin(), v.end(), [&total](double  v) { total += v; });
cout << "The sum of the values is: " << total << endl;
cout << "The mean value is: " << total/v.size() << endl;
Community
  • 1
  • 1
John Dibling
  • 99,718
  • 31
  • 186
  • 324
1

Just use:

for (int i = 0; i < v.size(); i++)
{
    v[i] -= valueToSubstract;
}

Or its equivalent (and more readable?):

for (int i = 0; i < v.size(); i++)
    v[i] = v[i] - valueToSubstract;
Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
1

You might want to consider using some algorithms instead:

// read in the data:
std::copy(std::istream_iterator<double>(input), 
          std::istream_iterator<double>(),
          std::back_inserter(v));

sum = std::accumulate(v.begin(), v.end(), 0);
average = sum / v.size();

You can modify the values with std::transform, though until we get lambda expressions (C++0x) it may be more trouble than it's worth:

class difference { 
    double base;
public:
    difference(double b) : base(b) {}
    double operator()(double v) { return v-base; }
};

std::transform(v.begin(), v.end(), v.begin(), difference(average));
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
1
int main() {
  using namespace std;

  fstream input ("input.txt");
  if (!input) return 1;

  vector<double> v;
  for (double d; input >> d;) {
    v.push_back(d);
  }
  if (v.empty()) return 1;

  double total = std::accumulate(v.begin(), v.end(), 0.0);
  double mean = total / v.size();

  cout << "The values in the file input.txt are:\n";
  for (vector<double>::const_iterator x = v.begin(); x != v.end(); ++x) {
    cout << *x << '\n';
  }
  cout << "The sum of the values is: " << total << '\n';
  cout << "The mean value is: " << mean << '\n';
  cout << "After subtracting the mean, The values are:\n";
  for (vector<double>::const_iterator x = v.begin(); x != v.end(); ++x) {
    cout << *x - mean << '\n';  // outputs without changing
    *x -= mean;  // changes the values in the vector
  }

  return 0;
}
Fred Nurk
  • 13,952
  • 4
  • 37
  • 63