Reputation: 53
Guys, I am writing a method for rounding. Input is a decimal type (four decimal places guaranteed). The rounding rule is that 0.005 or less is ignored, i.e. look at third decimal place - if it is <= 5, round down else round up. Some use cases : 82.3657 -> 82.36, 82.3667 -> 82.37, 82.5967 -> 82.60, 82.9958 -> 82.99, 82.9968 -> 83.00 Any good ideas? I have worked it out as follows.
private decimal CustomRound(decimal x)
{
decimal rX = Math.Truncate(x * 100) / 100;
decimal x3DecPlaces = Math.Truncate(x * 1000) / 1000;
decimal t = (x3DecPlaces * 1000) % 10;
if (t >= 6)
rX = rX + 0.01m;
return rX;
}
Upvotes: 5
Views: 4666
Reputation: 7614
How do you want to handle negative values? I suppose you would want -13.999 to round to -14 not to -13.99 right?
In that case your +/- 0.01m
should depend on whether x
is negative or positive.
This is an easier way to do it:
decimal CustomRound(decimal x)
{
var offset = x >= 0 ? -0.001m : 0.001m;
return Decimal.Round(x + offset, 2, MidpointRounding.AwayFromZero);
}
Upvotes: 0
Reputation: 1500675
I don't believe there's anything built-in for that, because it's a pretty unusual requirement (for example the idea that 1.3358 is closer to 1.33 than to 1.34 is odd). Your code looks reasonably appropriate.
EDIT: You can't use MidpointRounding
to get the effect you want here, because the point at which you start rounding up isn't the midpoint - it's (say) 1.336 rather than the normal 1.335. Only 1.335 is treated as the midpoint between 1.33 and 1.34, because that is the mid-point. You've effectively got a biased rounding here in an unusual way.
You can't even just truncate to three DP and then use MidpointRounding
, as there's no "towards zero" mode.
One slightly odd option would be to effectively perform the bias yourself:
private static decimal CustomRound(decimal x)
{
return decimal.Round(x - 0.001m, 2, MidpointRounding.AwayFromZero);
}
So it would treat 82.3657 as 82.3647 and round that to 82.36; it would treat 82.3667 and 82.3657 and round it to 82.37, and it would treat 82.5967 as 82.5957 and round it to 82.60 etc. I think that does what you want - but only for positive values. You'd need to work out exactly what behaviour you want for negative values.
Whatever you do, you need to document it very clearly :)
Just as a matter of preference, I would use decimal.Truncate
rather than Math.Truncate
, just to make it clearer that everything really is done with decimals.
Upvotes: 7