From 6a8bad8500641584a4f02c1970b8d4d1f07455b3 Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Mon, 19 Aug 2024 20:34:31 +0200 Subject: [PATCH] 0.2.0 RunAvgWeight --- libraries/RunAvgWeight/CHANGELOG.md | 8 +++ libraries/RunAvgWeight/README.md | 22 ++++++- libraries/RunAvgWeight/RunAvgWeight.cpp | 60 +++++++++++++------ libraries/RunAvgWeight/RunAvgWeight.h | 9 +-- .../examples/raw_test/raw_test.ino | 22 ++++++- libraries/RunAvgWeight/keywords.txt | 6 +- libraries/RunAvgWeight/library.json | 2 +- libraries/RunAvgWeight/library.properties | 2 +- 8 files changed, 98 insertions(+), 33 deletions(-) diff --git a/libraries/RunAvgWeight/CHANGELOG.md b/libraries/RunAvgWeight/CHANGELOG.md index f2cb75e5..facc4a47 100644 --- a/libraries/RunAvgWeight/CHANGELOG.md +++ b/libraries/RunAvgWeight/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.2.0] - 2024-08-12 +- Fix #6, **float getFastAverage()** => fix **clear()** +- Fix #4, add **float getCoefficientOfVariation()** +- add bool return value for **clear(), addValue()** +- update readme.md +- update keywords.txt + +---- ## [0.1.1] - 2024-07-01 - update documentation diff --git a/libraries/RunAvgWeight/README.md b/libraries/RunAvgWeight/README.md index f7cf8bf8..57b06413 100644 --- a/libraries/RunAvgWeight/README.md +++ b/libraries/RunAvgWeight/README.md @@ -36,6 +36,10 @@ possibly introduces an ever increasing error. In tests with **RunningAverage** library (with equal weights), adding up to 1500000 numbers this error was always small. Still you need to be aware of this limit. +### 0.2.0 breaking change + +Fixed #6 by fixing **clear()**, previous versions are now obsolete. + #### Related @@ -49,6 +53,7 @@ this error was always small. Still you need to be aware of this limit. - https://github.com/RobTillaart/statHelpers - combinations & permutations - https://github.com/RobTillaart/printHelpers - print scientific format - https://github.com/RobTillaart/Statistic +- https://github.com/RobTillaart/Student ## Interface @@ -66,12 +71,17 @@ The object has no default size. ### Basic -- **void clear()** empties the internal buffers. -- **void addValue(float value, float weight = 1.0)** adds a new value to the object, +- **bool clear()** empties the internal buffers. +- **bool addValue(float value, float weight = 1.0)** adds a new value to the object, if the internal buffer is full, the oldest element is removed. The default weight is 1.0 so one can use this class as a "unweighted" running average too, albeit with the extra overhead. **addValue()** updates the sum of values and weights for the **getFastAverage()** function. + + +The following functions returns NAN if there are no values present (count == 0) or +of internal array is not allocated. + - **float getValue(uint16_t position)** returns the value at **position** from the additions. Position 0 is the first one to disappear. - **float getWeight(uint16_t position)** returns the weight at **position** from the additions. @@ -88,12 +98,20 @@ improve its accuracy again. - **float getStandardDeviation()** returns the standard deviation of the current content. More than one element needs to be added to be calculable. - **float getStandardError()** returns the standard error of the current content. +- **float getCoefficientOfVariation()** returns coefficient of variation. +This is defined as standardDeviation / Average. +It indicates if the distribution is relative small ( < 1) or relative wide ( > 1). +Note it has no meaning when the average is zero (or close to zero). - **float getMin()** returns minimum value since last **clear()**. This value does not need to be in the internal buffer any more. Useful for graphing long term minima. +Note the returned minimum is **unweighted.** - **float getMax()** returns maximum value since last **clear()**. This value does not need to be in the internal buffer any more. Useful for graphing long term maxima. +Note the returned maximum is **unweighted.** - **float getMinInBuffer()** returns minimum value in the internal buffer. +Note the returned minimum is **unweighted.** - **float getMaxInBuffer()** returns maximum value in the internal buffer. +Note the returned maximum is **unweighted.** ### Admin functions diff --git a/libraries/RunAvgWeight/RunAvgWeight.cpp b/libraries/RunAvgWeight/RunAvgWeight.cpp index 88021e1a..9bcae61e 100644 --- a/libraries/RunAvgWeight/RunAvgWeight.cpp +++ b/libraries/RunAvgWeight/RunAvgWeight.cpp @@ -1,7 +1,7 @@ // // FILE: RunAvgWeight.cpp // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 +// VERSION: 0.2.0 // DATE: 2024-06-30 // PURPOSE: Arduino library to calculate the running average with weights by means of a circular buffer // URL: https://github.com/RobTillaart/RunAvgWeight @@ -31,7 +31,7 @@ RunAvgWeight::~RunAvgWeight() // resets all counters -void RunAvgWeight::clear() +bool RunAvgWeight::clear() { _count = 0; _index = 0; @@ -39,41 +39,49 @@ void RunAvgWeight::clear() _sumWeights = 0.0; _min = NAN; _max = NAN; - for (uint16_t i = _size; i > 0; ) + if (_size == 0) { - // setting values and weight to zero keeps addValue simpler - _values[--i] = 0.0; - _weights[--i] = 0.0; + return false; } + for (uint16_t i = 0; i < _size; i++) + { + // setting values and weights to zero keeps addValue simpler + _values[i] = 0.0; + _weights[i] = 0.0; + } + return true; } // adds a new value to the data-set -void RunAvgWeight::addValue(const float value, const float weight) +bool RunAvgWeight::addValue(const float value, const float weight) { - if ((_values == NULL) || (_weights == NULL)) - { - return; - } + if (_size == 0) + { + return false; + } + // TODO weight should be > 0 or at least != 0? - _sumValues -= _values[_index]; + _sumValues -= _values[_index] * _weights[_index]; _values[_index] = value; - _sumValues += _values[_index]; + _sumValues += _values[_index] * weight; _sumWeights -= _weights[_index]; _weights[_index] = weight; _sumWeights += _weights[_index]; + + // update index (next spot to add value). _index++; - - if (_index == _size) _index = 0; // faster than % - + if (_index >= _size) _index = 0; // faster than % + // update count + if (_count < _size) _count++; + // handle min max - if (_count == 0) _min = _max = value; + if (_count == 1) _min = _max = value; else if (value < _min) _min = value; else if (value > _max) _max = value; - // update count as last otherwise if ( _count == 0) above will fail - if (_count < _size) _count++; + return true; } @@ -193,6 +201,20 @@ float RunAvgWeight::getStandardError() } +// Return coefficient of variation. +// If buffer is empty or has only one element or zero average, return NAN. +float RunAvgWeight::getCoefficientOfVariation() +{ + float temp = getStandardDeviation(); + if (temp == NAN) return NAN; + if (_sumValues == 0) return NAN; + + // float cv = temp * getFastAverage(); + float cv = temp * _sumWeights / _sumValues; + return cv; +} + + ///////////////////////////////////////////////////////////////////// diff --git a/libraries/RunAvgWeight/RunAvgWeight.h b/libraries/RunAvgWeight/RunAvgWeight.h index 24228980..affc5be6 100644 --- a/libraries/RunAvgWeight/RunAvgWeight.h +++ b/libraries/RunAvgWeight/RunAvgWeight.h @@ -2,7 +2,7 @@ // // FILE: RunAvgWeight.h // AUTHOR: Rob Tillaart -// VERSION: 0.1.1 +// VERSION: 0.2.0 // DATE: 2024-06-30 // PURPOSE: Arduino library to calculate the running average with weights by means of a circular buffer // URL: https://github.com/RobTillaart/RunAvgWeight @@ -13,7 +13,7 @@ #include "Arduino.h" -#define RUNAVGWEIGHT_LIB_VERSION (F("0.1.1")) +#define RUNAVGWEIGHT_LIB_VERSION (F("0.2.0")) class RunAvgWeight @@ -22,8 +22,8 @@ public: explicit RunAvgWeight(const uint16_t size); ~RunAvgWeight(); - void clear(); - void addValue(const float value, const float weight = 1.0); + bool clear(); + bool addValue(const float value, const float weight = 1.0); float getValue(const uint16_t position); float getWeight(const uint16_t position); @@ -38,6 +38,7 @@ public: // weight <> 1 float getStandardDeviation(); float getStandardError(); + float getCoefficientOfVariation(); // returns min/max added to the data-set since last clear. // values without weight! diff --git a/libraries/RunAvgWeight/examples/raw_test/raw_test.ino b/libraries/RunAvgWeight/examples/raw_test/raw_test.ino index 79507db9..542c79a3 100644 --- a/libraries/RunAvgWeight/examples/raw_test/raw_test.ino +++ b/libraries/RunAvgWeight/examples/raw_test/raw_test.ino @@ -29,7 +29,21 @@ void setup(void) float value = i * 0.01 + 1; float weight = sqrt(i); myRA.addValue(value, weight); - Serial.print(myRA.bufferIsFull()); + + Serial.print(value); + Serial.print("\t"); + Serial.print(weight); + Serial.print("\t"); + Serial.print(myRA.getCount()); + Serial.print("\t"); + Serial.print(myRA.getSumValues(), 3); + Serial.print("\t"); + Serial.print(myRA.getSumWeights(), 3); + Serial.print("\t\t"); + Serial.print(myRA.getFastAverage(), 3); + Serial.print("\t"); + Serial.print(myRA.getAverage(), 3); + Serial.println(); } Serial.println(); Serial.println(); @@ -51,10 +65,12 @@ void setup(void) Serial.println(myRA.getCount()); Serial.println(); - Serial.print("AVG:\t"); - Serial.println(myRA.getAverage(), 5); + // first do fast to see if it is right + // if done after getAverage() it is same by definition. Serial.print("AVG(f):\t"); Serial.println(myRA.getFastAverage(), 5); + Serial.print("AVG:\t"); + Serial.println(myRA.getAverage(), 5); Serial.println(); Serial.print("STDDEV:\t"); diff --git a/libraries/RunAvgWeight/keywords.txt b/libraries/RunAvgWeight/keywords.txt index 5bc337eb..15792c88 100644 --- a/libraries/RunAvgWeight/keywords.txt +++ b/libraries/RunAvgWeight/keywords.txt @@ -15,6 +15,7 @@ getAverage KEYWORD2 getFastAverage KEYWORD2 getStandardDeviation KEYWORD2 getStandardError KEYWORD2 +getCoefficientOfVariation KEYWORD2 getMin KEYWORD2 getMax KEYWORD2 @@ -22,15 +23,14 @@ getMinInBuffer KEYWORD2 getMaxInBuffer KEYWORD2 bufferIsFull KEYWORD2 +getSize KEYWORD2 +getCount KEYWORD2 getElementValue KEYWORD2 getElementWeight KEYWORD2 getSumValues KEYWORD2 getSumWeights KEYWORD2 -getSize KEYWORD2 -getCount KEYWORD2 - # Instances (KEYWORD2) diff --git a/libraries/RunAvgWeight/library.json b/libraries/RunAvgWeight/library.json index d8e65e18..9f263226 100644 --- a/libraries/RunAvgWeight/library.json +++ b/libraries/RunAvgWeight/library.json @@ -15,7 +15,7 @@ "type": "git", "url": "https://github.com/RobTillaart/RunAvgWeight.git" }, - "version": "0.1.1", + "version": "0.2.0", "license": "MIT", "frameworks": "*", "platforms": "*", diff --git a/libraries/RunAvgWeight/library.properties b/libraries/RunAvgWeight/library.properties index 51d3ad57..728ae471 100644 --- a/libraries/RunAvgWeight/library.properties +++ b/libraries/RunAvgWeight/library.properties @@ -1,5 +1,5 @@ name=RunAvgWeight -version=0.1.1 +version=0.2.0 author=Rob Tillaart maintainer=Rob Tillaart sentence=Running Average with weight of N elements.