Click here to Skip to main content
15,889,335 members
Home / Discussions / C / C++ / MFC
   

C / C++ / MFC

 
GeneralRe: C/C++ Pin
Member 1100457311-Aug-14 19:16
Member 1100457311-Aug-14 19:16 
AnswerRe: C/C++ Pin
Satya Chamakuri11-Aug-14 21:06
Satya Chamakuri11-Aug-14 21:06 
AnswerRe: C/C++ Pin
Cristian Amarie14-Aug-14 22:10
Cristian Amarie14-Aug-14 22:10 
GeneralCalculute average value of large array Pin
wayne wu9-Aug-14 14:55
wayne wu9-Aug-14 14:55 
AnswerRe: Calculute average value of large array Pin
Jochen Arndt9-Aug-14 21:41
professionalJochen Arndt9-Aug-14 21:41 
GeneralRe: Calculute average value of large array Pin
k505410-Aug-14 2:19
mvek505410-Aug-14 2:19 
AnswerRe: Calculute average value of large array Pin
David Crow11-Aug-14 5:54
David Crow11-Aug-14 5:54 
GeneralRe: Calculute average value of large array Pin
Stefan_Lang11-Aug-14 23:07
Stefan_Lang11-Aug-14 23:07 
I've taken the link provided above (about cumulative average) as an inspiration to calculate the average incrementally, in a way that no intermediate value gets larger than about three times the maximum absolute value being added. Since I wasn't sure about various effects, such as the current average going negative, I added some test code and asserts to verify it actually works as intended. See the code below:
C++
#define TEST_RANGE
#ifdef TEST_RANGE
#include <assert.h>
void minmax(const double newval, double&minv, double&maxv) {
   if (newval < minv)
      minv = newval;
   else if (newval > maxv)
      maxv = newval;
}
#endif
template <class basetype, class container_iterator>
basetype average(const container_iterator& start, const container_iterator& end) {
   basetype cumulated_average = 0;
   basetype cumulated_remainder = 0;
   basetype addendum = 0;
#ifdef TEST_RANGE
   double real_avg = 0.0;
   double val_min = *start;
   double val_max = *start;
   double avg_min = cumulated_average;
   double avg_max = cumulated_average;
   double rem_min = cumulated_remainder;
   double rem_max = cumulated_remainder;
#endif
   long long n_values = 0;
   for (auto pvalue = start; pvalue != end; ++pvalue) {
      ++n_values;
      addendum = cumulated_remainder - cumulated_average + *pvalue;
      cumulated_average += addendum/n_values;
      cumulated_remainder = addendum%n_values;
#ifdef TEST_RANGE
      real_avg += *pvalue;
      assert((char)(n_values*cumulated_average + cumulated_remainder - real_avg) == 0);
      minmax(*pvalue, val_min, val_max);
      minmax(cumulated_average, avg_min, avg_max);
      minmax(cumulated_remainder, rem_min, rem_max);
#endif
   }
#ifdef TEST_RANGE
   assert (fabs(n_values*cumulated_average - real_avg) < n_values);
   real_avg /= (double)n_values;
#endif
   return cumulated_average;
}
void test_average() {
   char cvalues[] = { 13,7,-27, 34, -3, 22, 33, -1, 18, 29,
                      13,7,-27, 34, -3, 22, 33, -1, 18, 29,
                      13,7,-27, 34, -3, 22, 33, -1, 18, 29,
                      13,7,-27, 34, -3, 22, 33, -1, 18, 29,
                      13,7,-27, 34, -3, 22, 33, -1, 18, 29
                    };
   auto cavg = average<char>(cvalues+0, cvalues+50);
}

The last line is how it's used. For passing the values, you can pass any pair of iterators that delimit the range, including simple pointers (as I've done here), provided that these iterators can be incremented and dereferenced. In this example, the cumulative average does go negative a few times, and the total sum adds up to 625, way above the maximum a char can hold.

Note that you may not use a signed type for n_values: I originally used a signed type, but then found that this led to some nasty signed/unsigned conversion effects. You could probably get rid of that with proper casting though.


P.S. these are the formulas I've used:

The general idea is to have two values that correspond to the rounded average, and the remainder of the division, like this:
C++
Cum_avg(n) := sum(x1 ... xn) \ n
Cum_rem(n) := sum(x1 ... xn) % n

These two values then fulfil the follwing equation:
C++
sum(x1...xn) = n*Cum_avg(n) + Cum_rem(n)


The values for the next iteration are then calculated based on the previous values like this:
C++
Cum_avg(n+1) := sum(x1...xn+1) \(n+1)
              = (sum(x1...xn)+xn+1) \(n+1)
              = (n*Cum_avg(n)+Cum_rem(n)+xn+1) \(n+1)
              = ((n+1)*Cum_avg(n)-Cum_avg(n)+Cum_rem(n)+xn+1) \(n+1)
              = Cum_avg(n) + (-Cum_avg(n)+Cum_rem(n)+xn+1) \(n+1)


I've used a helper variable called addendum to hold the divisor of the second term. This term is just a sum of three values that are going to be in the normal value range, so the worst that can happen here is an overflow of that term. I still suspect that this can happen under certain circumstances, so the calculation of addendum may need some reworking!

The remainder of the next iteration is then simply the remainder of the division of addendum:
C++
Cum_rem(n+1) := addendum % (n+1)

GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)

QuestionApparently different behaviour assigning C string to std::string, for Relese/Debug Pin
piul8-Aug-14 4:36
piul8-Aug-14 4:36 
AnswerRe: Apparently different behaviour assigning C string to std::string, for Relese/Debug Pin
jeron18-Aug-14 5:00
jeron18-Aug-14 5:00 
GeneralRe: Apparently different behaviour assigning C string to std::string, for Relese/Debug Pin
piul10-Aug-14 21:39
piul10-Aug-14 21:39 
AnswerRe: Apparently different behaviour assigning C string to std::string, for Relese/Debug Pin
Richard MacCutchan8-Aug-14 5:57
mveRichard MacCutchan8-Aug-14 5:57 
AnswerRe: Apparently different behaviour assigning C string to std::string, for Relese/Debug Pin
«_Superman_»8-Aug-14 18:58
professional«_Superman_»8-Aug-14 18:58 
GeneralRe: Apparently different behaviour assigning C string to std::string, for Relese/Debug Pin
piul10-Aug-14 21:42
piul10-Aug-14 21:42 
QuestionHow to design (and do I want) an API? Pin
piul6-Aug-14 2:31
piul6-Aug-14 2:31 
AnswerRe: How to design (and do I want) an API? Pin
Espen Harlinn6-Aug-14 2:55
professionalEspen Harlinn6-Aug-14 2:55 
GeneralRe: How to design (and do I want) an API? Pin
piul6-Aug-14 2:59
piul6-Aug-14 2:59 
GeneralRe: How to design (and do I want) an API? Pin
Espen Harlinn6-Aug-14 3:09
professionalEspen Harlinn6-Aug-14 3:09 
AnswerRe: How to design (and do I want) an API? Pin
Cristian Amarie14-Aug-14 22:16
Cristian Amarie14-Aug-14 22:16 
QuestionConvert console to windows gui application Pin
Member 109951396-Aug-14 0:12
Member 109951396-Aug-14 0:12 
AnswerRe: Convert console to windows gui application Pin
Richard MacCutchan6-Aug-14 1:06
mveRichard MacCutchan6-Aug-14 1:06 
AnswerRe: Convert console to windows gui application Pin
Joe Woodbury6-Aug-14 15:38
professionalJoe Woodbury6-Aug-14 15:38 
AnswerRe: Convert console to windows gui application Pin
Cristian Amarie17-Aug-14 19:33
Cristian Amarie17-Aug-14 19:33 
Questionwhat is zed doing here? Pin
Alex Sturza5-Aug-14 8:29
Alex Sturza5-Aug-14 8:29 
AnswerRe: what is zed doing here? Pin
CPallini5-Aug-14 10:02
mveCPallini5-Aug-14 10:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.