1. ## 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 = 0; phase < 1.; phase += phaseinc)  {   //printf("%f\n", phase);   last_value = phase;  }     printf("actual last phase value -> %f\n", last_value); }  ```

2. 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.

3. 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 = 0; phase < 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. thanks!

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

CHUN

5. 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

6. hi dave:

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 = 0; phase < 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. Originally Posted by chunlee
hi dave:

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

8. 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. 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.