I am using Visual Studio Professional 2012. I created a new C# ConsoleApplication, targeting .NET Framework 4.5, with following code:
static void Main(string[] args)
{
double x = 2.44445;
double y = Math.Round(x, 4, MidpointRounding.AwayFromZero);
Console.WriteLine(y);
Console.ReadKey();
}
The expected result should be 2.4445, but it actually returns 2.4444. //Same result with previous framework version, and I tried VCE2010.
I know such problem usually results from the way double data type is stored (i.e. finite decimals converted to infinite binary fraction). But I didn't expect this to happen with only 5 decimal digits like 2.44445
I'm worrying if such thing could happen with even shorter decimals. I would also like to learn a safer way to round (using away from zero convention) in C#. Thanks.
Round(Double, Int32, MidpointRounding) This method is used to rounds a double precision floating-point value to a specified number of fractional digits. A parameter specifies how to round the value if it is midway between two numbers.
Rounding away from zeroMidpoint values are rounded to the next number away from zero. For example, 3.75 rounds to 3.8, 3.85 rounds to 3.9, -3.75 rounds to -3.8, and -3.85 rounds to -3.9. This form of rounding is represented by the MidpointRounding.
50000001" will always round up and ". 4999999" will always round down the the nearest integer. So a 15.5 can never become a 14. Any value that is larger than 14.5 and smaller than 15.5 will round to 15 any value larger than 15.5 and smaller than 16.5 will round to 16.
Use Math. Ceiling(87.124563563566) or Math. Floor(87.124563563566) for always rounding up or rounding down.
This is indeed due to the fragile precision of floating-point numbers. 0.5 can be stored perfectly in IEEE floating point, but 0.45, 0.445 etc. cannot. For example, the actual value that is stored when you specify 2.44445 is 11009049289107177/4503599627370496 which is 2.44449999999999989519494647... It should now be obvious why the number is rounded the way it is.
If you need to store fractional numbers precisely, consider using the decimal
type instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With