Andrew Que
Sites list
Photos
Computers
Projects
Contact
Main
Next week Previous week
 Aug 31 to Aug 25  -  Aug 24 to Aug 18  -  Aug 17 to Aug 11  -  Aug 10 to Aug 4 -  Aug 3 to Jul 28 
November - October - September - August - July - June - May
2013 - 2012 - 2011 - 2010 - 2009
Current week

+ Add a comment
Xen's Electromagnet
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-10
   This evening Xen learned how to make an electric magnet.  We used a nail, some magnet wire, and my DC power supply.  Our first magnet had a single row of wire and was so weak it couldn't even pick up a sewing pin.  For our second magnet we decided wrapping by hand took too long so I got out the drill.  We wound the magnet in seconds, and this magnet was better.  However the gauge wire we had selected got hot after a few seconds of operation.  So we wound a third magnet and this one did much better.  It was able to pick up objects heaver than itself.  Seen here is Xen using the magnet to lift a nail and a razor blade.
No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (Full size)
Show all photos from 2012-08-01
   Moon rise.
No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-02
   State Street at dawn.
No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-05
   Camp.
No comments have been added
+ Add a comment
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-02
   This is a shot from a few mornings ago.  While I was approaching State St. I saw this frame and I had to stop and capture it.  There is some interesting color contrast—blue sky, white building, yellow-orange tint from the street light.  There is also some texture contrast.  A solid blue sky, rough brick, shinny smooth tile, and the chain linked fence.  I found it interesting.
   At work I've been learning C Sharp.  Today I learned about how the language implements interfaces and abstract classes.  I also learned the type-checking is often done at run-time rather than compile time.  This I really don't like because I'd rather have type checking errors reported when I'm building rather than when I'm trying to run on the target system.  In addition, exceptions seem to lock our application and the entire system—and this makes for an irritating debug process.  But I am using a microsoft programming environment, and it's a long way from the stability I got use to working in aerospace.
No comments have been added
+ Add a comment
Cannon Fire
(600x600) (900x900) (1800x1800) (3600x3600) (Full size)
Show all photos from 2012-08-05
   Went with Amber to a Civil War reenactment in Boscobel, Wisconsin.  There was a fairly large group of precipitants which made for a good battle.  The cannon fire was really great—you could feel the concussion in your chest.  There was also a good demonstration of Civil War battlefield medical treatment.  While the presents of anesthetic was an improvement over Revolutionary War era medicine it still left a lot to be desired.  I also found it interesting that doctors treated wounded from both sides.
No comments have been added
- Average Class + Add a comment

I thought I'd share a simple moving average template class. I got this idea while at work yesterday when talking to an electrical engineer about making a writing efficient average function. Afterward I continued to think about ways to continue to improve upon the idea.

A mean average is simply the sum of all the data divided by the number of data points. A moving average assumes a fixed number of data points. When new data is added, the oldest sample is lost replaced with the new data added. So the mean average reflects the average over the most recent data only. This functions like a low-pass filter and is often used as an easy way to clean up analog signals.

What if the moving average was over a huge number of samples, and the type of samples was some kind of object with computationally difficult math operations? Perhaps the moving average is being preformed on a long list of arbitrary-precision data points. Adding up all the data points and dividing by the number of points could take too long.

We can speed the process of taking the average by keeping a sum. When a new point is added, the oldest data point is subtracted from the sum, and the new data added. In this way the only math operation needed to take the average at any time is dividing by the number of samples.

In making an average class I also considered how to resize the moving average. If the average becomes larger, empty data is simply placed at the end. If it becomes smaller, only the most recent samples need to be saved.

Here is a C++ implementation:

//==============================================================================
// Template class for keeping a moving average.
// Assumes math operations on 'TYPE' are computationally expensive, so used
// sparingly.
//==============================================================================
templateclass TYPE >
  class Average
  {
    protected:
      // Storage of all the data points that make the average.
      TYPE * array;

      // A representation of zero in the type of this template.
      TYPE zero;

      // Index into 'array' to save next data point.
      unsigned currentIndex;

      // How many data points are currently in array.
      unsigned top;

      // Length of 'array'.
      unsigned length;

      // Running sum used to compute average.
      TYPE sum;

    public:
      //------------------------------------------------------------------------
      // Create moving average with 'lengthParameter' number of samples to be
      // averaged together.
      //------------------------------------------------------------------------
      Average( unsigned lengthParameter )
      {
        length = lengthParameter;

        // Allocate storage for
        array = new TYPE[ length ];

        // We need a definition of zero, so make a cast to get this.
        // NOTE: This is important if TYPE is truly a class.
        zero = static_cast< TYPE >( 0 );

        reset();
      }

      //------------------------------------------------------------------------
      // Reset all data in average.
      // NOTE: Average result will be the equivalent of zero.
      //------------------------------------------------------------------------
      void reset()
      {
        // Empty array.
        for ( currentIndex = 0; currentIndex < length; ++currentIndex )
          array[ currentIndex ] = zero;

        currentIndex = 0;
        top = 0;
        sum = 0;
      }

      //------------------------------------------------------------------------
      // Resize the number of samples used in average.
      // If the size becomes larger, then the average will not change until
      // more data is added.
      // If the size becomes smaller, then the last 'newLength' samples will be
      // copied to new average.
      //------------------------------------------------------------------------
      void resize( unsigned newLength )
      {
        // Allocate memory for new array.
        TYPE * newArray = new TYPE[ newLength ];

        // Reset sum.
        sum = zero;
        for ( unsigned count = newLength; count > 0--count )
        {
          unsigned index = count - 1;

          // Do we have data to copy from the old array at this index?
          if ( index < top )
          {
            // Get previous data index.
            if ( currentIndex == 0 )
              currentIndex = length - 1;
            else
              currentIndex -= 1;

            // Save data in new array.
            newArray[ index ] = array[ currentIndex ];

            // Sum this data.
            sum += newArray[ index ];
          }
          else
            // Set this position to zero.
            newArray[ index ] = zero;
       }

        // Delete old array holder and switch to new array.
        delete array;
        array = newArray;

        // Move top if the new length is lower than previous top.
        if ( top > newLength )
          top = newLength;

        // New length.
        length = newLength;

        // Set new index location.
        currentIndex = top;
        if ( currentIndex >= length )
          currentIndex = 0;
      }

      //------------------------------------------------------------------------
      // Return the computed average.
      // NOTE: Uses the data in the average thus far.  If average isn't full,
      // then only those data points in the array are used.
      //------------------------------------------------------------------------
      TYPE get() const
      {
        TYPE result;

        if ( top > 0 )
          result = sum / static_cast< TYPE >( top );
        else
          result = zero;

        return result;
      }

      //------------------------------------------------------------------------
      // Return the number of data points in the moving average so far.
      //------------------------------------------------------------------------
      unsigned getNumberOfDataPoints() const
      {
        return top;
      }

      //------------------------------------------------------------------------
      // Add new data to average.
      //------------------------------------------------------------------------
      void push( TYPE newData )
      {
        // Remove old data from average sum.
        sum -= array[ currentIndex ];

        // Add new data to average sum.
        sum += newData;

        // Save new data.
        array[ currentIndex ] = newData;

        // Advance index.
        ++currentIndex;

        // If this marks the top...
        if ( currentIndex > top )
          // Update the top.
          top = currentIndex;

        // Wrap-around index.
        if ( currentIndex >= length )
          currentIndex = 0;
      }

  };

Download the code

Use it like this:

  Average< int > average( 5 );

  average.push( 1 );
  average.push( 2 );
  average.push( 3 );

  int meanAverage = average.get();

This code will create a rolling average of up to 5 elements.  It then adds the data [1, 2, 3] to the average.  'meanAverage' will be 2.

No comments have been added


Designed and maintained by Andrew Que
(C) Copyright 2001-2012