max
max

Reputation: 61

Trying to get a number within an array that is twice the average

I have been assigned to set up an array with points. I am told to get the maximum value, average, and within this same array, if any point in the array is twice the average, I should cout an "outlier." So far I have gotten the average and maximum numbers in the array. but i am unable to set the programme to cout the outlier. Instead it gives me a multiple of the average. here is the programme;

int main()
{
    const int max = 10;
    int ary[max]={4, 32, 9, 7, 14, 12,  13, 17, 19, 18};
    int i,maxv;
    double out,sum=0;
    double av;


    maxv= ary[0];

    for(i=0; i<max; i++)
    {
        if(maxv<ary[i])
            maxv= ary[i];

    }
    cout<<"maximum value: "<<maxv<<endl;

    for(i=0; i<max; i++)
    {

        sum = sum + ary[i];
        av = sum / max;
    }
    cout<<"average: "<<av<<endl;

    out = av * 2;

    if(ary[i]>out)
    {
        cout<<"outlier:  "<<maxv<<endl;
    }
    else
    {
        cout<<"ok"<<endl;
    }


    return 0;
}

Upvotes: 6

Views: 349

Answers (5)

Escualo
Escualo

Reputation: 42082

I prepared the following program (mostly for my own learning). It attempts to make as much use of the C++ Standard Library as possible.

#include<iostream>
#include<iterator>
#include<vector>
#include<algorithm>

int main() {
  std::vector<float> nums;
  // this will read the numbers from standard input; it will continue
  // for as long as it can read floats (to stop you can enter a
  // letter, or press Ctrl+D)
  std::copy(std::istream_iterator<float>(std::cin),
            std::istream_iterator<float>(),
            std::back_insert_iterator<std::vector<float>>(nums));

  // calculate the mean
  float mean = std::accumulate(nums.begin(), nums.end(), 0) / nums.size();

  std::cout<<"Mean of "<<nums.size()<<" numbers: "<<mean<<std::endl;

  // create a lambda function which returns true if a number is BELOW
  // twice the mean
  auto fun = [&mean](float x) {return x < 2.0 * mean;};

  // partition the list of numbers: those for which the lambda is true
  // (i.e., the ones BELOW twice the man) will come before the
  // outliers; the stable sort ensures that within each partition the
  // numbers come in the original order
  auto mark = std::stable_partition(nums.begin(), nums.end(), fun);

  // mark gives an iterator to the first element of the second
  // partition; it it is before the end we report the outliers
  if(mark!=nums.end()) {

    std::cout<<"Found "<<nums.end()-mark<<" outliers:"<<std::endl;

    for(auto it=mark; it!=nums.end(); ++it) {
      std::cout<<"\t"<<*it<<std::endl;
    }

  } else {
    std::cout<<"No outliers found."<<std::endl;
  }

  return 0;
}

My output (compiled with g++ (GCC 4.7.2) using the -std=c++11 flag).

[Prompt] ./a.out
1 2 3 4 5 20 f # the f is to end the stream of numbers; press enter
Mean of 6 numbers: 5
Found 1 outliers:
    20

Upvotes: 0

fredoverflow
fredoverflow

Reputation: 263138

Here is a C++ solution to your assignment, but you probably won't be allowed to hand that in ;-)

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>

int main()
{
    const int N = 10;
    int ary[N] = {4, 32, 9, 7, 14, 12, 13, 17, 19, 18};

    int max = *std::max_element(ary, ary + N);
    std::cout << "maximum: " << max << std::endl;

    double average = std::accumulate(ary, ary + N, 0.0) / N;
    std::cout << "average: " << average << std::endl;

    std::cout << "outlier: ";
    std::remove_copy_if(ary, ary + N,
                        std::ostream_iterator<int>(std::cout, " "),
                        std::bind2nd(std::less_equal<double>(), 2 * average));
    std::cout << std::endl;
}

Upvotes: 4

Stewart
Stewart

Reputation: 4028

Your code contains a subtle and tricky to spot bug. You're using ary[i] after the final for loop. At this point, the value of i is equal to max, so your if statement is comparing random memory because you're going off the end of the array.

Since this is C++ and not C, you could have avoided this particular bug by declaring your loop variables in the for loop like this

for (int i = 0; i < max; ++i) {
    ....
}

Upvotes: 10

the_drow
the_drow

Reputation: 19181

If it is exactly twice the average it should be '==' instead of bigger then twice the avarage.
Aslo why are you outputing maxv? Try to use more meaningful names.
Shouldn't you print ary[i] instead? Also, why aren't you looping the array again with a for loop? Shouldn't you iterate all over it to find all outliners or should only the last element be checked for an outliner.

Upvotes: 0

Stephen
Stephen

Reputation: 49166

You'll need to use two for-loops. You should be traversing the ary and checking each element against out, then cout << ary[i].

This would probably be a little more obvious if you declared your variables where they are used, in the smallest scope possible.

For example:

for (int i = 0; ...) {
}

and

double outlier = avg * 2;

By the way, this may be a little over-your-head (right now), but STL provides functions for determining the max (max_element) and sum (accumulate) of an array. It might be interesting reading.

Upvotes: 0

Related Questions