Rounding double values in C#

53,338

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.

Share:
53,338
Steve
Author by

Steve

Updated on February 03, 2020

Comments

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