Luca Petrini
Luca Petrini

Reputation: 1745

How can I customize the behavior of Math.Round in .NET?

I have to use a round method that follows this behavior:

7.00 -> round -> 7
7.50 -> round -> 7
7.51 -> round -> 8

I tried to use Math.Round, but it works a little bit different.

Dim val As Decimal = 7.5
Dim a As Decimal = Math.Round(val, 0) ' -> 8
Dim b As Decimal = Math.Round(val, 0, MidpointRounding.AwayFromZero) ' -> 8
Dim c As Decimal = Math.Round(val, 0, MidpointRounding.ToEven) ' -> 8

How can I implement my rounding logic?

Upvotes: 0

Views: 1739

Answers (4)

Alex Zhevzhik
Alex Zhevzhik

Reputation: 3407

Midpoint couldn't provide appropriate functionality. Take a look at first and third rows in the table in remarks. If you change your val to 6.5, you will get expected behaviour, but not with 7.5.

You should write your own implementation of such rounding.

Javed Akram's implementation is good, but it works completely wrong with negative numbers. As you didn't provide details of rounding of negative numbers, I suppose standart rounding suits. In addition you should take into account "special" double values:

static class Helper
{
    public static double Round(double val)
    {
        if (Double.IsNaN(val) || Double.IsNegativeInfinity(val) || Double.IsPositiveInfinity(val))
        {
            return val;
        }

        var decimalPart = Math.Truncate(val);
        if (val >= 0)
        {
            if (val - decimalPart <= 0.5)
            {
                return Math.Floor(val);
            }
            else
            {
                return Math.Ceiling(val);
            }
        }
        else
        {
            return Math.Round(val, 0);
        }
    }
}

Upvotes: 1

Kevin
Kevin

Reputation: 5694

You could subtract 0.01 from the total and then call Math.round(..).

double d = 7.5;
double result = Math.Round(d - 0.01);

If the number is negative you will have to do the following to get the same result:

double d = -7.5;
if (d < 0)
{
    double tmp = Math.Abs(d) - 0.01;
    double result = -Math.Round(tmp);
}

Working example here.

Note however that this behaviour is probably not what you want as noted by several others.

If you read the comments of this answer, @alex zhevzhik also noted that this solution will fail if the input would have more than 2 decimals.

Upvotes: 2

Javed Akram
Javed Akram

Reputation: 15344

    Dim i As Decimal
    Dim j As Integer
    Dim k As Decimal

    i = 7.51
    k = i - Math.Truncate(i)  'decimal part of number

    If (k <= 0.5) Then
        j = Math.Floor(i)
    Else
        j = Math.Ceiling(i)
    End If

Upvotes: 0

Christian
Christian

Reputation: 4375

Well I don't know if there is a Math.Round method that does what you want, but I think you will need to write your own. Because normally, 7.5 would be rounded to 8, unless I forgot everything learned in highschool.

Upvotes: 0

Related Questions