简体   繁体   中英

Rounding (math.h) in C not working as it should

#include <stdio.h>
#include <math.h>

int main(){
  printf("Rounded value of 6*0.95*0.25 = %.2f\n", round(6*0.95*0.25*100)/100);
  printf("Rounded value of 1.425 = %.2f\n", round(1.425*100)/100);
}

I have a suspicion that it is to do with the accuracy of the doubles and respective arithmetic, but how I can solve this (such that 6*0.95*0.25 which is 1.425 will round to 1.43) I have no idea....

(I am using the GNU compiler latest version (1.7 something))

help appreciated

I am trying to round to 2 dp

The following is the output:

Rounded value of 6*0.95*0.25 = 1.42
Rounded value of 1.425 = 1.43

( https://onlinegdb.com/r1ZtZ2lCW )

I want

Rounded value of 6*0.95*0.25 = 1.43
Rounded value of 1.425 = 1.43

Rounding in math.h is working exactly as it should. When you give your program a decimal number like 1.425 it stores this as the closest binary representation of the number. The number 1.425 = 57 / 40. Because 40 isn't a power of 2 there isn't an exact binary representation of this number. In this case the stored number is a little less than 1.425 so the number rounds down.

The only general solution to stop this rounding disparity is to use a decimal floating point implementation. This will be considerably slower than a binary floating point implementation unless it is supported by hardware.

My solution was to be to make the following function:

double twoDPRoundHack(double x){
  return round(round(x*10000)/100)/100;
}

This appears to work

#include <stdio.h>
#include <math.h>

double twoDPRoundHack(double x){
  return round(round(x*1000)/100)/100;
}

int main(){
  printf("Rounded value of 6*0.95*0.25 = %.2f\n", 
         twoDPRoundHack(6*0.95*0.25*100));
   printf("Rounded value of 1.425 = %.2f\n", round(1.425*100)/100);
}

clearly, it was being stored as 142.499999999999...

If you are doing the calculation out side of print statement you will get the correct answer

#include <stdio.h>
#include <math.h>

int main (){
    float value = 6*0.95*0.25;
    printf ("Rounded value of 6*0.95*0.25 = %.2f\n",
    round(value*100)/100);

    printf ("Rounded value of 1.425 = %.2f\n", round (1.425 * 100) / 100);

}

Output

Rounded value of 6*0.95*0.25 = 1.43
Rounded value of 1.425 = 1.43 

This certainly does seem to not be working as expected. I don't know if it helps much, but changing the order of the multiplication seems to resolve the issue.

#include <stdio.h>
#include <math.h>

int main(){
  printf("Rounded value of 6*0.95*0.25 (hundred last) = %.2f\n", round(6*0.95*0.25*100)/100);
  printf("Rounded value of 6*0.95*0.25 (hundred first) = %.2f\n", round(100*6*0.95*0.25)/100);
  printf("Rounded value of 1.425 = %.2f\n", round(100*1.425)/100);
}

output

Rounded value of 6*0.95*0.25 (hundred last) = 1.42
Rounded value of 6*0.95*0.25 (hundred first) = 1.43
Rounded value of 1.425 = 1.43

Which is obviously super dumb! Maybe there is a clue in that to the cause of the issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM