## How C# rounds decimal numbers

2010-09-03

You might have known the following example:

``````Math.Round(3.44, 1); //Returns 3.4.
Math.Round(3.45, 1); //Returns 3.4.
Math.Round(3.46, 1); //Returns 3.5.
``````

(code sample from Microsft msdn site)

So here you might find something is different. why 3.45 is 3.4? Yes, in C#, the Math.Round method **normally (but not always, see more examples below) **make all 0.5 and less down to 0, make all 0.6 and more up to 1, 0.5 will not be 1, but will be 0 !

So, in C#, we should know how decimal is handled in C#.

Here another strange example:

``````            double r;
r = Math.Round(1.5);       // result = 2.0
r = Math.Round(2.5);       // result = 2.0
``````

Why above 2 lines all get 2?

Here is an important rule: Midpoint Rules:

1: "To Even" rule: By default, when the number is 0.5 (number is rounded is exactly half way between two integers), Math.Round always select the closest even value; 2: "Away From Zero" rule: when the rounded value is midway between the two possible outcomes, always choose the value that is furthest from zero. For positive values this means rounding upwards and for negative numbers the result is rounded downwards.

Microsoft site provides a good example for above rules:

``````// This example demonstrates the Math.Round() method in conjunction
// with the MidpointRounding enumeration.
using System;

class Sample
{
public static void Main()
{
decimal result = 0.0m;
decimal posValue =  3.45m;
decimal negValue = -3.45m;

// By default, round a positive and a negative value to the nearest even number.
// The precision of the result is 1 decimal place.

result = Math.Round(posValue, 1);
Console.WriteLine("{0,4} = Math.Round({1,5}, 1)", result, posValue);
result = Math.Round(negValue, 1);
Console.WriteLine("{0,4} = Math.Round({1,5}, 1)", result, negValue);
Console.WriteLine();

// Round a positive value to the nearest even number, then to the nearest number away from zero.
// The precision of the result is 1 decimal place.

result = Math.Round(posValue, 1, MidpointRounding.ToEven);
Console.WriteLine("{0,4} = Math.Round({1,5}, 1, MidpointRounding.ToEven)", result, posValue);
result = Math.Round(posValue, 1, MidpointRounding.AwayFromZero);
Console.WriteLine("{0,4} = Math.Round({1,5}, 1, MidpointRounding.AwayFromZero)", result, posValue);
Console.WriteLine();

// Round a negative value to the nearest even number, then to the nearest number away from zero.
// The precision of the result is 1 decimal place.

result = Math.Round(negValue, 1, MidpointRounding.ToEven);
Console.WriteLine("{0,4} = Math.Round({1,5}, 1, MidpointRounding.ToEven)", result, negValue);
result = Math.Round(negValue, 1, MidpointRounding.AwayFromZero);
Console.WriteLine("{0,4} = Math.Round({1,5}, 1, MidpointRounding.AwayFromZero)", result, negValue);
Console.WriteLine();
}
}
/*
This code example produces the following results:

3.4 = Math.Round( 3.45, 1)
-3.4 = Math.Round(-3.45, 1)

3.4 = Math.Round( 3.45, 1, MidpointRounding.ToEven)
3.5 = Math.Round( 3.45, 1, MidpointRounding.AwayFromZero)

-3.4 = Math.Round(-3.45, 1, MidpointRounding.ToEven)
-3.5 = Math.Round(-3.45, 1, MidpointRounding.AwayFromZero)

*/
``````

When you are confused by Math.Round, please just give a MidpointRounding parameter in your Round method.

OR, you can use other methods:

Truncation

``````decimal.Truncate(2.3M);    // result = 2
decimal.Truncate(2.9M);    // result = 2
decimal.Truncate(1M);      // result = 1
decimal.Truncate(-2.3M);   // result = -2
decimal.Truncate(-2.9M);   // result = -2```
``````

Floor and Ceiling

``````decimal.Floor(2.2M);       // result = 2
decimal.Floor(2.9M);       // result = 2
decimal.Floor(-2.3M);      // result = -3

decimal.Ceiling(2.2M);     // result = 3
decimal.Ceiling(2.7M);     // result = 3
result = decimal.Ceiling(-3.3M);    // result = -3
result = decimal.Ceiling(-3.9M);    // result = -3
``````