# Average four 16 bit numbers in Hi-Tech C

Discussion in 'Embedded Systems and Microcontrollers' started by Guinness1759, Jun 8, 2011.

1. ### Guinness1759 Thread Starter Member

Dec 10, 2010
64
0
Lets say I have temp1, temp2, temp3, and temp4 and they are 16 bit numbers. How do I take the average of them?

I tried

volatile unsigned char temp1[2], temp2[2], temp3[2], temp4[2], ave_temp[2];

ave_temp = (temp1+temp2+temp3+temp4)/4

but it's giving me a bunch of errors.

2. ### RiJoRI Well-Known Member

Aug 15, 2007
536
26
16 bit numbers are usually ints. An int (16 bits) is NOT the same as two (8-bit) chars.

And if you are adding 4 16-bit ints, you may overflow to the 17th and 18th bits.

You are trying to do (T1+T2+T3+T4)/4. Another -- and in this case better -- way is (T1/4)+(T2/4)+(T3/4)+(T4/4). But unless the numbers are multiples of four you'll have a rounding error.

Adding 2 to each number will round up and give a better -- not precise, but better -- answer.

Work it out on paper. You can use 8- or 4- bit numbers. Remember, dividing by 4 is the same as shifting right twice.

HTH,
--Rich

Guinness1759 likes this.
3. ### Guinness1759 Thread Starter Member

Dec 10, 2010
64
0
edit: thanks. I think I decided that I'm going to send the data out and do processing on the computer side, that way it can keep track of decimals.

Last edited: Jun 8, 2011
4. ### Papabravo Expert

Feb 24, 2006
10,340
1,850
What decimals?

You should do the arithmetic using multi-byte precision operations. If you have a 24-bit accumulator then overflow with 16-bit unsigned ints will be no problem. This is probably beyond your capability if you're willing to give up so easily.

Guinness1759 likes this.
5. ### THE_RB AAC Fanatic!

Feb 11, 2008
5,435
1,305
All you need is a 32bit variable to add the numbers in;

Code ( (Unknown Language)):
1.
2. unsigned long math;  // 32bit variable
3.
4. math = 0;
5. math += temp1;
6. math += temp2;
7. math += temp3;
8. math += temp4;
9. math += 2;  // add half the divisor, is compensation for integer rounding
10. math = (math / 4);
11. // at this point math is guaranteed <65536 so it is safe to put back
12. // into a 16bit variable if needed.
13.

Guinness1759 likes this.
6. ### Alberto Active Member

Nov 7, 2008
169
36
There is a turn around when averaging big numbers that can generate an overflow during addition.

Here the method:

Sort in ascending way all the values

Take the first value (the smallest).

Subtract the first value from all the other values and add together the differences.

Average the sum of the difference.

Add the average to the smallest number you have choosen.

And the result is the same algebric average of the conventional calculation.

Cheers

Alberto

7. ### THE_RB AAC Fanatic!

Feb 11, 2008
5,435
1,305
Interesting method! But what if the smallest sample is 0 and the other 3 samples are 65535? To average the 3 differences you would still need to add 3* 65535 which still overflows the 16bit accumulator...

Another way would be to reduce the resolution of the 4 samples to where they could not overflow a 16bit accumulator when added.

If you divide all the 4 16bit samples by 4 and then add them, the result must still fit in a 16bit accumulator. You can negate the rounding down error by adding 2 to each sample before it is divided by 4, provided every sample is <=65533.

If you need the full range 0-65535 then you could accumulate the bottom 2 bits of each sample in a second accumulator (8bit size) before they are divided by 4 and then apply it later.

8. ### t06afre AAC Fanatic!

May 11, 2009
5,939
1,222
In C we have something named Integral Promotion. It may "kick in" in your case. But it will depend on your C compiler. Also drop the divide operation. As it seams your compiler is struggling with this math operation. Instead use the Right shift (>>) operator. The value of a right-shift expression x >> y is x / (2^y). So a divide by 4 is easy to do. And the shift operator is part of the backbone functions in any C compiler

Last edited: Jun 12, 2011