how to write a function to provide maximum, minimum, mean over time?

I would love to have a function to provide maximum, minimum, mean over time?
float statistic( variable, action, type){}

action should be
‘w’ write the value
‘r’ read the value
‘z’ reset the value

type should be
1 min value
2 mean value
3 max value

But how to store the values between calls?
when I use static float, will it use another storage for every instance of the called function?
Or should I use an array and pass a third parameter for the instance number?

Or do you know someone, who has done it the better way?

How many different variables do you want to report on ?

RIN67630:
when I use static float, will it use another storage for every instance of the called function?

No.

I think you just need a struct like this:

struct statistics
{
  float minimum ;
  float maximum ;
  float mean ;
} stats ;

Not clear why you want a function.

The better way, is to make a class with initialization methods, set and get methods for the read, write, reset, etc. Then you can make an individual statistics object for each variable that you want to track.

Variables declared with the 'static' keyword inside a function, retain their value between calls. So you can use that to accumulate averages and so on. But your proposal for an interface is seriously awkward.

Functions don't have "instances", they only have "calls". Having to pass to a function, the number of times it has been called, doesn't seem like anything that could ever be useful. So I'll assume that you are grabbing at straws.

What do you want to happen when you write the mean?!?

  float foo = 27.3;
  statistic(foo, 'w', 2);

How about when you reset the max?!?

statistic(foo, 'z', 3);

aarg:
Functions don't have "instances", they only have "calls".
Variables declared with the 'static' keyword inside a function, retain their value between calls. So you can use that to accumulate averages and so on.

That is what I feared.
It will not make a difference between
-two calls at different program locations (for different passed variables) and
-two subsequent calls at iterations (for the same passed variable).

So I will have to use static arrays and pass on different indices for each program location to avoid a mess between the different usages.

johnwasser:
What do you want to happen when you write the mean?!?

  float foo = 27.3;

statistic(foo, 'w', 2);





> Obviously it will sum the values and increment a counter.
> 
> 
> 
> 
> > How about when you reset the max?!?
> > 
> > 
> > ```
> > statistic(foo, 'z', 3);
> > ```
> 
> 
> (assuming positive values) Resetting the max is not an issue, resetting the min implies to know to which value.

UKHeliBob:
How many different variables do you want to report on ?

Many. That is the problem to solve.

If you want to apply the same routines to multiple datum, the answer is a class.

http://www.cplusplus.com/doc/tutorial/classes/

I have no idea how static arrays could help you. It sounds like you're cooking up a kludge.

RIN67630:
Many. That is the problem to solve.

Are the variables related to each other, such as values read from several sensors of the same type, or a bunch of largely unrelated values ?

what about a struct that contains a pointer to a variable, perhaps a type and max, min and mean and possible the number of entries resulting in the mean if not simply a running average (leaky integrated)

corresponding function write, read or reset. (of course you could create a class) these functions are passed a pointer to the variable and maybe it's types.

they search thru a table of the above structs using the variable address as the key. if not found, they allocate or populate an unused table entry, initializing the max = min = mean = value. An unused entry has a NULL address value.

hopefully you get the idea

This seems to work for your basic statistics. Start by changing your ‘float’ variables to ‘StatFloat’. You can use a StatFloat on the left side of an assignment. If you have a ‘StatFloat’ on both sides of an assignment you will need to cast the right side as ‘(float)’ or the right side will get copied over the left side, overwriting all the statistics.

class StatFloat : public Printable
{
  public:
    StatFloat(float val)  // Constructor with value
    {
      value = val;
      max = val;
      min = val;
      sum = val;
      count = 1;
    }


    StatFloat()  // Constructor without value (defaults to 0.0)
    {
      value = 0.0;
      max = 0.0;
      min = 0.0;
      sum = 0.0;
      count = 0;
    }


    StatFloat & operator = (const float arg)
    {
      value = arg;
      if (value > max) max = value;
      if (value < min) min = value;
      sum += value;
      count++;
      return *this;
    }


    // Overloaded float cast
    operator float() const
    {
      return value;
    }


    float read()
    {
      return value;
    }


    float getMax()
    {
      return max;
    }


    float getMin()
    {
      return min;
    }


    float getMean()
    {
      if (count == 0)
        return NAN;
      return sum / count;
    }


    size_t printTo(Print& p) const
    {
      return p.print(value);
    }


  private:
    float value;
    float max, min, sum;
    unsigned count;
};


void setup()
{
  Serial.begin(115200);


  StatFloat sf;
  Serial.println("Uninitialized:");
  Serial.println(sf);
  Serial.println(sf.getMin());
  Serial.println(sf.getMean());
  Serial.println(sf.getMax());


  sf = 23.0;
  Serial.println("Assigned 23.0:");
  Serial.println(sf);
  Serial.println(sf.getMin());
  Serial.println(sf.getMean());
  Serial.println(sf.getMax());


  sf = 92.66;
  Serial.println("Assigned 92.66:");
  Serial.println(sf);
  Serial.println(sf.getMin());
  Serial.println(sf.getMean());
  Serial.println(sf.getMax());


  StatFloat another = 15.5;


  sf = (float) another;
  Serial.println("Assigned (float)another (set to 15.5):");
  Serial.println(sf);
  Serial.println(sf.getMin());
  Serial.println(sf.getMean());
  Serial.println(sf.getMax());


  another = 68.4;
  float f = another;
  sf = f;
  Serial.println("Assigned 'f' (set to 68.4 via 'another'):");
  Serial.println(sf);
  Serial.println(sf.getMin());
  Serial.println(sf.getMean());
  Serial.println(sf.getMax());


  another = 22.22;
  sf = another;
  Serial.println("Assigned 'another' (set to 22.22):");
  Serial.println(sf);
  Serial.println(sf.getMin());
  Serial.println(sf.getMean());
  Serial.println(sf.getMax());
}


void loop() {}

Output:

Uninitialized:
0.00
0.00
nan
0.00
Assigned 23.0:
23.00
0.00
23.00
23.00
Assigned 92.66:
92.66
0.00
57.83
92.66
Assigned (float)another (set to 15.5):
15.50
0.00
43.72
92.66
Assigned 'f' (set to 68.4 via 'another'):
68.40
0.00
49.89
92.66
Assigned 'another' (set to 22.22):
22.22
15.50
35.37
68.40

johnwasser:
This seems to work for your basic statistics. Start by changing your 'float' variables to 'StatFloat'. You can use a StatFloat on the left side of an assignment. If you have a 'StatFloat' on both sides of an assignment you will need to cast the right side as '(float)' or the right side will get copied over the left side, overwriting all the statistics.

Thank you.
I will go through this tomorrow on a fresh new day...