[time-nuts] PLL Math Question

Dennis Ferguson dennis.c.ferguson at gmail.com
Thu Mar 13 14:58:48 EDT 2014


On 12 Mar, 2014, at 23:08 , Hal Murray <hmurray at megapathdsl.net> wrote:
> bob at evoria.net said:
>> In the moving averages I'm doing, I'm saving the last bit to be shifted out
>> and if it's a 1 (i.e. 0.5) I increase the result by 1. 
> 
> That's just rounding up at an important place.  It's probably a good idea, 
> but doesn't cover the area I was trying to point out.  Let me try again...
> 
> Suppose you are doing:
>  x_avg = x_avg + (x - x_avg) * a_avg;
> 
> For exponential smoothing, a_avg will be a fraction.  Let's pick a_avg to be 
> 1/8.  That's a right shift by 3 bits.  I don't think there is anything magic 
> about shifting, but that makes a particular case easy to spot and discuss.
> 
> Suppose x_avg is 0 and x has been 0 for a while.  Everything is stable.  Now change x to 2.  (x - x_avg) is 2, the shift kicks it off the edge, so x_avg doesn't change.  (It went 2 bits off, so your round up doesn't catch it.)  The response to small steps is to ignore them.

Note that you can't do fixed-point computations exactly the same way
you would do it in floating point, you often need to rearrange the equations
a bit.  You can usually find a rearrangement which provides equivalent
results, however.  Let's define an extra variable, x_sum, where

    x_avg = x_sum * a_avg;

The equation above can then be rewritten in terms of x_sum, i.e.

    x_sum = x_sum * (1 - a_avg) + x;

With an a_avg of 1/8 you'll instead be multiplying x_sum by 7, shifting
it right 3 bits (you might want to round before the shift) and adding x.
The new value of x_avg can be computed from the new value of x_sum with a
shift (you might want to round that too), or you could pretend that x_sum
is a fixed-point number with the decimal point 3 bits from the right.
In either case x_sum carries enough bits that you don't lose precision.

Dennis Ferguson


More information about the time-nuts mailing list