Thread: float accumulator precision?

  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    23

    float accumulator precision?

    hi there:

    i have been experimenting with simple saw-tooth oscillator emulation before i actually do the DSP code. its essentially working out the phase increment value and just accumulate that into a float. repeat the process once the accumulator (phase) is larger than 1.

    my question is that, in theory, once i know how much phase should increase by each time, i should be able to know in advance the last value of phase before it goes over 1, right?

    but, as it turns out in my code, the perdicted last phase value is different from the actual value of the accumulator.

    is this the precision problem with floats or am i doing something wrong in my code?

    cheers

    CHUN
    PHP Code:
    main()
    {
     
    float freq 200
     
    float phaseinc freq * (1./44100);
     
    float phase
     
    float last_value
     
     
    printf("freq ->%f\n"freq);
     
    printf("phase increased by -> %f\n",phaseinc);
     
    printf("perdict last phase value -> %f\n"1-phaseinc);
     
     for(
    phase 0phase 1.phase += phaseinc)
     {
      
    //printf("%f\n", phase);
      
    last_value phase;
     } 
     
     
    printf("actual last phase value -> %f\n"last_value);


  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Floating point numbers are not precise. Here is nearly all you'll need to know when dealing with floating point numbers and their problems.

    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by chunlee
    hi there:

    i have been experimenting with simple saw-tooth oscillator emulation before i actually do the DSP code. its essentially working out the phase increment value and just accumulate that into a float. repeat the process once the accumulator (phase) is larger than 1.

    my question is that, in theory, once i know how much phase should increase by each time, i should be able to know in advance the last value of phase before it goes over 1, right?

    but, as it turns out in my code, the perdicted last phase value is different from the actual value of the accumulator.

    is this the precision problem with floats or am i doing something wrong in my code?

    cheers

    CHUN
    PHP Code:
    main()
    {
     
    float freq 200
     
    float phaseinc freq * (1./44100);
     
    float phase
     
    float last_value
     
     
    printf("freq ->%f\n"freq);
     
    printf("phase increased by -> %f\n",phaseinc);
     
    printf("perdict last phase value -> %f\n"1-phaseinc);
     
     for(
    phase 0phase 1.phase += phaseinc)
     {
      
    //printf("%f\n", phase);
      
    last_value phase;
     } 
     
     
    printf("actual last phase value -> %f\n"last_value);

    Your problem is not roundoff error (If you change floats to doubles you will see that the error is about the same.)
    You have defined phaseinc so that it takes 220.5 steps to get from 0 to 1.


    Try this with different frequencies and phaseinc definitions:

    Code:
    #include <stdio.h>
    
    int main()
    {
      double freq = 200;
      double phaseinc = freq * (1./44100);
      double phase;
      double last_value;
      int i;
    
      printf("freq                     -> %f\n", freq);
      printf("phase increased by       -> %.8e\n",phaseinc);
      printf("predict last phase value -> %.8e\n\n", 1-phaseinc);
    
      printf("Number of steps to get to 1 = %f\n\n", 1.0/phaseinc);
    
      i = 0;
      for(phase = 0; phase < 1.; phase += phaseinc)
      {
        //printf("%f\n", phase);
        last_value = phase;
        i++;
      }
      printf("Number of steps = %d\n", i);
    
      printf("actual last phase value  -> %15.8e\n", last_value);
      printf("actual - predicted       -> %15.8e\n", last_value - (1.0 - phaseinc));
    
      return 0;
    }
    Regards,

    Dave

  4. #4
    Registered User
    Join Date
    Nov 2004
    Posts
    23
    thanks!

    so that's just the way it is with floating numbers, not my code is wrong...


    CHUN

  5. #5
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by chunlee
    thanks!

    so that's just the way it is with floating numbers, not my code is wrong...


    CHUN

    No! You are apparently expecting to get from zero to 1 in an integer number of steps. It takes 220.5 steps with the step size you have selected. The problem is not (not) floating point roundoff error.

    I wouldn't go so far as to say your code is "wrong"; I would say that your expectations are wrong. (Whether it does what you want it to do is up to you.)

    Regards,

    Dave
    Last edited by Dave Evans; 11-11-2004 at 10:58 PM.

  6. #6
    Registered User
    Join Date
    Nov 2004
    Posts
    23
    hi dave:

    it was funny timming, when i posted the reply to quzah and i saw your reply, so i only read yours after i posted my first reply

    yes, i ran your code and can see what you mean. i also tried this following modification (deriving phaseinc form int):

    PHP Code:
    main()
    {
     
     
    float freq 200
     
    //float phaseinc = freq * (1./44100);
     
    float phase
     
    float last_value
     
    int steps 44100 freq;
     
    float phaseinc 1. steps;  
     
    int i
     
     
    printf("freq ->%f\n"freq);
     
    printf("phase increased by -> %f\n",phaseinc);
     
    printf("perdict last phase value -> %f\n"1-phaseinc);
     
    printf("perdict steps -> %d\n"steps);
     
     
    i=0
     
     for(
    phase 0phase 1.phase += phaseinc)
     {
      
    //printf("%f\n", phase);
      
    last_value phase;
      
    i++; 
     } 
     
     
    printf("actual last phase value -> %f :: actual steps -> %d\n"last_value,i); 
    }

  7. #7
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by chunlee
    hi dave:

    it was funny timming, when i posted the reply to quzah and i saw your reply, so i only read yours after i posted my first reply

    yes, i ran your code and can see what you mean. i also tried this following modification (deriving phaseinc form int):
    Yep. Now, if you print out the error at the end:

    Code:
    printf("error = %15.8e\n", 1.0 - last_value);
    You will see that with floats, the error is about 7.75e-7, and with doubles the error is about 4.22e-18.

    That's the effect of floating point (roundoff) error. That's about the best you can expect (floats have about 7 significant decimal digits, and doubles have about 17.)

    Regards,

    Dave
    Last edited by Dave Evans; 11-11-2004 at 10:59 PM.

  8. #8
    Registered User
    Join Date
    Nov 2004
    Posts
    23
    hi dave:

    thanks for your reply, i think i got it now. the second version of my code which derives phaseinc form int has the float roundoff error while my first verions was not so much so because i was asking it to go from 0 to 1 in 220.5 steps.

    cheers

    CHUN

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Let's review the origional question:
    my question is that, in theory, once i know how much phase should increase by each time, i should be able to know in advance the last value of phase before it goes over 1, right?
    Which translates, "Once I figure out my algorithm, I should be ok, right?"

    but, as it turns out in my code, the perdicted last phase value is different from the actual value of the accumulator.

    is this the precision problem with floats or am i doing something wrong in my code?
    Which translates to, "I don't get what I expect, is this a problem with floats?"

    To which I gave information on the problem with floating point numbers. It's up to you to figure out if your algorithm is wrong. At least that's how I see it.

    Quzah.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 05-13-2009, 03:25 PM
  2. Replies: 14
    Last Post: 06-28-2006, 01:58 AM
  3. Could somebody please help me with this C program
    By brett73 in forum C Programming
    Replies: 6
    Last Post: 11-25-2004, 02:19 AM
  4. Half-life SDK, where are the constants?
    By bennyandthejets in forum Game Programming
    Replies: 29
    Last Post: 08-25-2003, 11:58 AM
  5. How do you search & sort an array?
    By sketchit in forum C Programming
    Replies: 30
    Last Post: 11-03-2001, 05:26 PM