Round function off by 1 - C

74 views Asked by At
char note_array[] = "G#5";

int approx_freq = 880;

int result = 0;
if(note_array[1] == '#')
    approx_freq = round(approx_freq * pow(2, 1.0/12));
switch(note_array[0])
{
case 'A': result =  approx_freq;
    break;
case 'B': result = round(approx_freq * pow(2, 2.0/12));
    break;
case 'C': result = round(approx_freq / pow(2, 9.0/12));
    break;
case 'D': result = round(approx_freq / pow(2, 7.0/12));
    break;
case 'E': result = round(approx_freq / pow(2, 5.0/12));
    break;
case 'F': result = round(approx_freq / pow(2, 4.0/12));
    break;
case 'G': result = round(approx_freq / pow(2.0, 2.0/12));
    break;
default: return 1;
    break;
}
return result;

Output Coming - 830

Output Needed - 831

I know there is something wrong with my usage of the round function, but I don't know what I'm doing wrong. Can anybody please help me out?

2

There are 2 answers

1
Barmar On BEST ANSWER

You're rounding down when you do this step:

approx_freq = round(approx_freq * pow(2, 1.0/12));

The exact value is 932.3275230361799. This sets approx_freq to 932. Then when you do:

case 'G': result = round(approx_freq / pow(2.0, 2.0/12));
    break;

approx_freq / pow(2.0, 2.0/12)) is 830.3176053067962, which rounds to 830.

You shouldn't do rounding in your intermediate steps. Declare approx_freq to be float or double, and only round the final result. Then the last calculation will result in 830.609, which rounds up to 831.

0
Yunnosch On

Introduce an offset for selecting the border at which rounding down turns into rounding up. Do so in all calls to round(), e.g.

approx_freq = round(offset + approx_freq * pow(2, 1.0/12));

I am not sure, but I guess that the value of offset should be -0.5 for what you want.
Try and fine-tune yourself.

(Note, as other comments/answers have noted, that when to round is a tricky question. I recommend using the offset after double checking that rounding is needed in each case.)