... round a float
value, say val
to its nearest multiple of 0.05 ...
Given typical binary floating point, the best that can be had is
... round a float
value to nearest to a multiple of 0.05 R
and save as the nearest representable float
r
.
Method #1 is unclear in the corner cases. What OP has is not code, but an outline of code from a math perspective and not an actual C code one. I'd go with a variation on #2 that works very well. @Barmar
Almost method 2: Multiply, round, then divide.
#include <math.h>
double factor = 20.0;
float val = foo();
double_or_float rounded_val = round(val * factor)/factor;
This method has two subtle points that make it superior.
The multiplication is done with greater precision and range than the referenced answer - this allows for an exact product and a very precise quotient. If the product/quotient were calculated with only float
math, some edge cases would end up with the wrong answer and of course some large values would overflow to infinity.
"Ties are settled by taking lower value." is a tough and unusual goal. Sounds like a goal geared to skew selection. round(double)
nicely rounds half way cases away from zero regardless of the current rounding direction. To accomplish "lower", change the current rounding direction and use rint()
or nearbyint()
.
#include <fenv.h>
int current_rounding_direction = fegetround();
fesetround(FE_DOWNWARD);
double rounded_val = rint(val * factor)/factor;
fesetround(current_rounding_direction);
... method-2 yields wrong results some times...
OP needs to post the code and the exact values used and calculated for a quality explanation of the strength/weakness of various methods. Try printf("%a %a\n", val, rounded_val);
. Often, problems occurs due to imprecise understanding of the exact values used should code use printf("%f\n", val);
Further: "I already have upper and lower bounds of val
, say valU
and valL
respectively. I can do this in the following ways:"
This is doubtfully accurate as the deviation of valU
and valL
is just an iteration of the original problem - to find rounded_val
. The code to find valL
and valU
each needs an upper and lower bound, else what is to prevent range [valL ... valU]
from itself having inaccurate endpoints?