Rounding down to 2 decimal places in c#

49,878

Solution 1

The Math.Round(...) function has an Enum to tell it what rounding strategy to use. Unfortunately the two defined won't exactly fit your situation.

The two Midpoint Rounding modes are:

  1. AwayFromZero - When a number is halfway between two others, it is rounded toward the nearest number that is away from zero. (Aka, round up)
  2. ToEven - When a number is halfway between two others, it is rounded toward the nearest even number. (Will Favor .16 over .17, and .18 over .17)

What you want to use is Floor with some multiplication.

var output = Math.Floor((41.75 * 0.1) * 100) / 100;

The output variable should have 4.17 in it now.

In fact you can also write a function to take a variable length as well:

public decimal RoundDown(decimal i, double decimalPlaces)
{
   var power = Convert.ToDecimal(Math.Pow(10, decimalPlaces));
   return Math.Floor(i * power) / power;
}

Solution 2

public double RoundDown(double number, int decimalPlaces)
{
     return Math.Floor(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}

Solution 3

As of .NET Core 3.0 and the upcoming .NET Framework 5.0 the following is valid

Math.Round(41.75 * 0.1, 2, MidpointRounding.ToZero)

Solution 4

There is no native support for precision floor/ceillin in c#.

You can however mimic the functionality by multiplying the number, the floor, and then divide by the same multiplier.

eg,

decimal y = 4.314M;
decimal x = Math.Floor(y * 100) / 100;  // To two decimal places (use 1000 for 3 etc)
Console.WriteLine(x);  // 4.31

Not the ideal solution, but should work if the number is small.

Solution 5

One more solution is to make rounding toward zero from rounding away from zero. It should be something like this:

    static decimal DecimalTowardZero(decimal value, int decimals)
    {
        // rounding away from zero
        var rounded = decimal.Round(value, decimals, MidpointRounding.AwayFromZero);

        // if the absolute rounded result is greater 
        // than the absolute source number we need to correct result
        if (Math.Abs(rounded) > Math.Abs(value))
        {
            return rounded - new decimal(1, 0, 0, value < 0, (byte)decimals);
        }
        else
        {
            return rounded;
        }
    }
Share:
49,878
startupsmith
Author by

startupsmith

Software developer. Currently working with C# on Mono, Silverstripe, Mono for Android and Monotouch. I have also done a lot of work deploying servers to the cloud (EC2 and Rackspace).

Updated on July 09, 2022

Comments

  • startupsmith
    startupsmith almost 2 years

    How can I multiply two decimals and round the result down to 2 decimal places?

    For example if the equation is 41.75 x 0.1 the result will be 4.175. If I do this in c# with decimals it will automatically round up to 4.18. I would like to round down to 4.17.

    I tried using Math.Floor but it just rounds down to 4.00. Here is an example:

    Math.Floor (41.75 * 0.1);
    
  • Mat M
    Mat M over 10 years
    Actualy, it should work using the Math.Round Method (Decimal, Int32, MidpointRounding) overload (check stackoverflow.com/questions/13522095/…)
  • sandeep talabathula
    sandeep talabathula about 8 years
    i * power is an error. You meant double there might be.
  • Ruan
    Ruan almost 7 years
    You cant multiply a double with a decimal
  • Brandon Barkley
    Brandon Barkley over 5 years
    The MidpointRounding overload could solve the issue of .5 rounding down instead of up (if there were a strategy called "TowardZero"), but I believe the asker used a poor example. Their question indicated they wanted all numbers to round down to 2 digits. So 4.179999999 would be 4.17. If you only want midpoints to round down, you should use that overload, but if you want all to round down, you need the technique above or similar techniques in other answers.
  • softarn
    softarn almost 4 years
    This was almost 8 years ago. Is this still the best answer?
  • Jonathan Queipo
    Jonathan Queipo about 3 years
    Heads up! Depending on the device, this might lead to accuracy issues. When trying to apply this function to the value 10.40 at 2 decimal places, I got 10.39 on an Android device using Xamarin.
  • Jonathan Queipo
    Jonathan Queipo about 3 years
    Heads up! Depending on the device, this might lead to accuracy issues. When trying to apply this function to the value 10.40 at 2 decimal places, I got 10.39 on an Android device using Xamarin.
  • SteveC
    SteveC about 2 years
    I was hesitant to use this because the documentation I read describes "a number halfway between two others" but this does correctly answer the question depending on what you want with negatives. One might also consider ToNegativeInfinity