For the first time in my programming career (spanning more years than I care to tell ;o), I had to round to a negative number. In other words, to a number on the left side of the decimal. If, like me, you're not a math person, you might be saying, "huh?"
For example, I needed my code to turn a number like 1,550,875.45 into 1,551,000.00. Or to turn a number like 1,250.00 into 1,000.00. I've always rounded to X number of digits to the right of the decimal point. Usually I'll round to two decimal places, like when working with USD currency numbers, or to seven or so decimal places when dealing with numbers like interest rates. Never to negative decimal places.
Microsoft Excel calls this "rounding to the left of the decimal point", and makes it extremely easy to do, for example:
Microsoft Excel calls this "rounding to the left of the decimal point", and makes it extremely easy to do, for example:
=ROUND(1550875.45, -3)
But in C# the Math.Round function doesn't like being told to round to a negative number of digits. When I tried it, I got this error message:
Decimal can only round to between 0 and 28 digits of precision. Parameter name: decimals
Dang. That would have been really easy if it had worked. To solve the problem quickly (remember, I'm not a mathematician) I took to the web and found several possible solutions. Drawing from a couple of the solutions, after putting in my own tweaks and modifications, I ended up with this C# code:
public static decimal RoundTo(this decimal number, int roundTo)
{
if (System.Math.Abs(roundTo) > 28)
throw new ArgumentOutOfRangeException("roundTo", "Maximum rounding allowed before or after the decimal is 28 places.");
if (roundTo >= 0)
return decimal.Round(number, roundTo);
decimal roundFactor = (decimal) System.Math.Pow(10, -roundTo);
return decimal.Round(number / roundFactor, 0) * roundFactor;
}
Note that because my RoundTo method is an extension method, it must be in a static class, or it won't work. However, also because it is an extension method, it's a bit cleaner (more elegant, you could say) to call:
decimal beforeRoundTo = 1550875.45;
decimal afterRoundTo = beforeRoundTo.RoundTo(-3);
Anyhow, I hope this post helps you in that rare instance (which might be now) in your career when you need to round a number to the left of its decimal place.