Rounding double values in C#
Solution 1
Example of using decimal
, as Kibbee pointed out
double d = 1.275;
Math.Round(d, 2); // 1.27
Math.Round((decimal)d, 2); // 1.28
Solution 2
double d = 1.2345;
Math.Round(d, 2);
the code above should do the trick.
Solution 3
If you actually need to use double
just replace it below and it will work but with the usual precision problems of binary floating-point arithmetics.
There's most certainly a better way to implement the "rounding" (almost a kind of bankers' rounding) than my string juggling below.
public static decimal RoundI(decimal number, decimal roundingInterval)
{
if (roundingInterval == 0) { return 0;}
decimal intv = Math.Abs(roundingInterval);
decimal modulo = number % intv;
if ((intv - modulo) == modulo) {
var temp = (number - modulo).ToString("#.##################");
if (temp.Length != 0 && temp[temp.Length - 1] % 2 == 0) modulo *= -1;
}
else if ((intv - modulo) < modulo)
modulo = (intv - modulo);
else
modulo *= -1;
return number + modulo;
}
Solution 4
The examples using decimal casting provided in Jimmy's answer don't answer the question, since they do not show how to round a double value to any rounding precision value as requested. I believe the correct answer using decimal casting is the following:
public static double RoundI(double number, double roundingInterval)
{
return (double)((decimal)roundingInterval * Math.Round((decimal)number / (decimal)roundingInterval, MidpointRounding.AwayFromZero));
}
Because it uses decimal casting, this solution is subject to the casting errors mentioned by Jeppe Stig Nielsen in his comment to Jimmy's answer.
Also, note that I specified MidpointRounding.AwayFromZero, since that is consistent with the requester's specification that RoundI(1.2345, 0.001) should give 1.235.
Steve
Updated on February 03, 2020Comments
-
Steve over 4 years
I want a rounding method on double values in C#. It needs to be able to round a double value to any rounding precision value. My code on hand looks like:
public static double RoundI(double number, double roundingInterval) { if (roundingInterval == 0.0) { return; } double intv = Math.Abs(roundingInterval); double sign = Math.Sign(number); double val = Math.Abs(number); double valIntvRatio = val / intv; double k = Math.Floor(valIntvRatio); double m = valIntvRatio - k; bool mGreaterThanMidPoint = ((m - 0.5) >= 1e-14) ? true : false; bool mInMidpoint = (Math.Abs(m - 0.5) < 1e-14) ? true : false; return (mGreaterThanMidPoint || mInMidpoint) ? sign * ((k + 1) * intv) : sign * (k * intv); }
So RoundI(100, 3) should give 99 and RoundI(1.2345, 0.001) should give 1.235.
The problem is, RoundI(1.275, 0.01) returns 1.27, rather than 1.28. This is because when executing double valIntvRatio = val/intv, that is, double valIntvRatio = 1.275 / 0.01, it gives 0.12749999999999. I know this is a problem with double representation in any programming language. My question is, is there a standard code to do things like this, without the need to worry about precision on double? Here I set the tolerant to 1e-14, but this is too restrict for this problem and I don't know what is the correct tolerance to be set. Thank you for any help.