2
#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 d.p.

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

abaft
  • 152
  • 2
  • 12
  • 2
    What isn't working – BurnsBA Oct 27 '17 at 13:10
  • What is the output you get? What output did you expect? – Some programmer dude Oct 27 '17 at 13:10
  • By default the round function will round the value up if it is midway. However you can specify it the other way by sending another Boolean value to the constructor. – 0014 Oct 27 '17 at 13:13
  • Your first value is rounding `142.5` to `142`. Changing to `printf("Rounded value of 6*0.95*0.25 = %.2f\n", round(6*0.95*0.25*1000)/1000);` gives the output you want ...... for this specific instance. – BurnsBA Oct 27 '17 at 13:18
  • @BurnsBA True that will work, but in the larger program I am assigning the rounded value to another variable, I want the value rounded to 2 d.p. stored in memory somehow – abaft Oct 27 '17 at 13:20
  • What have you tried so far to store the value in memory somehow – BurnsBA Oct 27 '17 at 13:22
  • Your problem can be more succintly represented by: `printf("%f\n", 6.0 * 0.95*0.25 * 100.0); printf("%f\n", round(6.0 * 0.95*0.25 * 100.0)); printf("%f\n", round(142.5));`. Forget about the number of decimal points you're displaying. I suspect it's due to fundamental innacuracies when it comes to floating point arithmetic. – Steve Oct 27 '17 at 13:25
  • If the number ends on a 5, printf will wound to closest even number. – klutt Oct 27 '17 at 13:37
  • I am confident that either 1) your compiler is broken or 2) `printf()` is rounding down or 3) `printf("%.2f", ...)` is poorly implemented - most likely. `round()` is not the issue. Please report your result of using `"%.20f"` instead of `"%.2f"` in the two `printf()`. – chux - Reinstate Monica Oct 27 '17 at 20:28

4 Answers4

2

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.

James Snook
  • 4,063
  • 2
  • 18
  • 30
  • Disagree: OP's Issue is not about values near 1.425, but values near 1.43. OP's code calculates `6*0.95*0.25` which is 143.0 or at least near it. Even if it is a bit off like 143.0001... or 142.9999..., the result of `round(6 * 0.95 * 0.25 * 100)` will be 143.0 - exact. Then `round(6*0.95*0.25*100)/100` will be near 1.43. Unless the compiler is rounding toward 0 rather than the common round toward nearest, this should print `"1.43"`. – chux - Reinstate Monica Oct 27 '17 at 20:36
  • 1
    @chux If the OP only wants information about this exact calculation then the correct answer is `printf("1.43");`. The calculation you suggest `6 * 0.95 * 0.25 * 100` is `142.499...` to the computer which is closer to 142. `round(6 * 0.95 * 0.25 * 100)` = 142, try it. P.S. I checked by writing a Swift program, then double checked by trying it in C too. – James Snook Oct 28 '17 at 15:35
  • 1
    FWIW, you can also, in some cases, do the arithmetic using integers with an appropriate multiplier, then insert the point for display purposes. – al45tair Oct 29 '17 at 18:28
0

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

abaft
  • 152
  • 2
  • 12
0

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 
Sushin Pv
  • 1,826
  • 3
  • 22
  • 36
  • This idiom (`round(x*100)/100`) does not do what you might imagine. See https://stackoverflow.com/questions/829067/how-can-i-round-a-float-value-to-2-post-decimal-positions/6681911#6681911 – al45tair Oct 29 '17 at 18:29
0

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.

Matthew Hart
  • 359
  • 2
  • 10