-
-
Save bmccormack/d12f4bf0c96423d03f82 to your computer and use it in GitHub Desktop.
#include <stdio.h> | |
int movingAvg(int *ptrArrNumbers, long *ptrSum, int pos, int len, int nextNum) | |
{ | |
//Subtract the oldest number from the prev sum, add the new number | |
*ptrSum = *ptrSum - ptrArrNumbers[pos] + nextNum; | |
//Assign the nextNum to the position in the array | |
ptrArrNumbers[pos] = nextNum; | |
//return the average | |
return *ptrSum / len; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
// a sample array of numbers. The represent "readings" from a sensor over time | |
int sample[] = {50, 10, 20, 18, 20, 100, 18, 10, 13, 500, 50, 40, 10}; | |
// the size of this array represents how many numbers will be used | |
// to calculate the average | |
int arrNumbers[5] = {0}; | |
int pos = 0; | |
int newAvg = 0; | |
long sum = 0; | |
int len = sizeof(arrNumbers) / sizeof(int); | |
int count = sizeof(sample) / sizeof(int); | |
for(int i = 0; i < count; i++){ | |
newAvg = movingAvg(arrNumbers, &sum, pos, len, sample[i]); | |
printf("The new average is %d\n", newAvg); | |
pos++; | |
if (pos >= len){ | |
pos = 0; | |
} | |
} | |
return 0; | |
} |
Thank you for this nice piece of Code, compact and well written
Thanks for the code. Helpful for an ADC averaging routine
Thank you for the code. Worked perfectly in my application
Thank you so much! I am much appreciated.
Very good, thank you!
muito obrigado meu patrão.
how to do this using float values as input please tell me
I realize that there is a way to do that without using pointers and with only one function (whithout have to increment position in a outside way), if you declare the position variable "pos" as static and the sum variable ptrSum too you can have a code with the same funtionality like:
#include <stdio.h>
int movingAvg(int *ptrArrNumbers, int len, int nextNum)
{
static long Sum = 0;
static int pos = 0;
//Subtract the oldest number from the prev sum, add the new number
Sum = Sum - ptrArrNumbers[pos] + nextNum;
//Assign the nextNum to the position in the array
ptrArrNumbers[pos] = nextNum;
//Increment position internaly
pos++;
if (pos >= len){
pos = 0;
}
//return the average
return *ptrSum / len;
}
int main(int argc, char *argv[])
{
// a sample array of numbers. The represent "readings" from a sensor over time
int sample[] = {50, 10, 20, 18, 20, 100, 18, 10, 13, 500, 50, 40, 10};
// the size of this array represents how many numbers will be used
// to calculate the average
int arrNumbers[5] = {0};
int newAvg = 0;
int len = sizeof(arrNumbers) / sizeof(int);
int count = sizeof(sample) / sizeof(int);
for(int i = 0; i < count; i++){
newAvg = movingAvg(arrNumbers, len, sample[i]);
printf("The new average is %d\n", newAvg);
}
return 0;
}
@saifandro327 to do it using float values you just need to change the return(at declaration) and the last parameter from int
to float
like this:
float movingAvg(float *ptrArrNumbers, int len, float nextNum){
//Same code
}
OBS: Using the function with the variables pos and sum declared as static will be that the value stay preserved, if you want to reset the moving average may be usefull add a parameter to use as conditional state to clear/reset the sum of moving average like this:
int movingAvg(int *ptrArrNumbers, int len, int nextNum, bool reset)
{
static long Sum = 0;
static int pos = 0;
//check for reset request
if(reset){
Sum = 0;
pos = 0;
}
//Subtract the oldest number from the prev sum, add the new number
Sum = Sum - ptrArrNumbers[pos] + nextNum;
//Assign the nextNum to the position in the array
ptrArrNumbers[pos] = nextNum;
//Increment position internaly
pos++;
if (pos >= len){
pos = 0;
}
//return the average
return *ptrSum / len;
}
OBS: Using the function with the variables pos and sum declared as static will be that the value stay preserved, if you want to reset the moving average may be usefull add a parameter to use as conditional state to clear/reset the sum of moving average like this:
int movingAvg(int *ptrArrNumbers, int len, int nextNum, bool reset) { static long Sum = 0; static int pos = 0; //check for reset request if(reset){ Sum = 0; pos = 0; } //Subtract the oldest number from the prev sum, add the new number Sum = Sum - ptrArrNumbers[pos] + nextNum; //Assign the nextNum to the position in the array ptrArrNumbers[pos] = nextNum; //Increment position internaly pos++; if (pos >= len){ pos = 0; } //return the average return *ptrSum / len; }
Using Statics completely breaks the function being used simultaneously on different arrays. Never use statics on Utility functions unless you want a world of pain
@RichardPar that's a good point! I didn't think about this situation of use the function in different arrays!
@RichardPar that's a good point! I didn't think about this situation of use the function in different arrays!
Additionally..
//return the average
**return *ptrSum / len;**
The first run of the function will return the wrong average when there are less than LEN samples in the array.
wow u saved my life and my grade ily
in the above code instant of this sample array
int sample[] = {50, 10, 20, 18, 20, 100, 18, 10, 13, 500, 50, 40, 10};
can we use a sensor input for continuous signal output , for example
const int analog_pin = A0;
if i need a program for continuous sensor input what changes i need to do in this code. can someone help me with that?
Thank you for this implementation and for all the comments. Very helpful!
I rewrote the moving average using a struct.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
typedef struct moving_average
{
long sum;
int pos;
int * buffer;
int length;
bool is_filled;
}moving_average_t;
int movingAvg(moving_average_t * av_obj, int new_element)
{
//Subtract the oldest number from the prev sum, add the new number
av_obj->sum = av_obj->sum - av_obj->buffer[av_obj->pos] + new_element;
//Assign the nextNum to the position in the array
av_obj->buffer[av_obj->pos] = new_element;
//Increment position internaly
av_obj->pos++;
if (av_obj->pos >= av_obj->length){
av_obj->pos = 0;
av_obj->is_filled = true;
}
printf("is_filled %d", av_obj->is_filled);
//return the average
return av_obj->sum / (av_obj->is_filled ? av_obj->length:av_obj->pos);
}
moving_average_t * allocate_moving_average(int len)
{
moving_average_t * av_obj = malloc(sizeof(moving_average_t));
av_obj->sum = 0;
av_obj->pos = 0;
av_obj->length = len;
av_obj->is_filled = false;
av_obj->buffer = malloc(len * sizeof(int));
return av_obj;
}
void free_moving_average(moving_average_t * av_obj)
{
free(av_obj->buffer);
av_obj->buffer = NULL;
free(av_obj);
}
int main()
{
// a sample array of numbers. The represent "readings" from a sensor over time
int sample[] = {50, 10, 20, 18, 20, 100, 18, 10, 13, 500, 50, 40, 10};
// the size of this array represents how many numbers will be used
// to calculate the average
int newAvg = 0;
int count = sizeof(sample) / sizeof(int);
moving_average_t * sensor_av = allocate_moving_average(5);
for(int i = 0; i < count; i++){
newAvg = movingAvg(sensor_av, sample[i]);
printf("The new average is %d\n", newAvg);
}
free_moving_average(sensor_av);
sensor_av = NULL;
return 0;
}
What is sizeof(int) supposed to be the size of? "int" is a type. I am confused as to what needs to be in that field.
Thank you
What is sizeof(int) supposed to be the size of? "int" is a type
Depends on your targeted machine. On most PC, it's 4 bytes. However, other targets like Arduino Uno only have 2 bytes. So it's safer to write sizeof(int)
rather than directly write 4
.
For anyone who didn't familiar with C, this line
int count = sizeof(sample) / sizeof(int);
Counts how many elements in sample
array.
thank you very much. I applied used your code on my frequency counter machine.