39

I have a decimal number which can be like the following:

189.182

I want to round this up to 2 decimal places, so the output would be the following:

189.19

Is there built in functionality for this in the Math class, or something else? I know the ceiling function exists but this doesn't seem to do what I want - it'll round to the nearest int, so just '189' in this case.

Chris
  • 7,415
  • 21
  • 98
  • 190
  • 4
    Why marked as duplicate? OP asks to round up, other question asks to round down. – JC. Jun 30 '14 at 02:36
  • Without leaving decimal type: `public static decimal RoundUp(decimal input, int places) { if (places < 0) return input; decimal multiplier = 1; for (int i = 0; i < places; ++i) multiplier *= 10; return (Math.Ceiling(input * multiplier) / multiplier); }` – Steve Hibbert Jul 11 '14 at 09:26

8 Answers8

60

Multiply by 100, call ceiling, divide by 100 does what I think you are asking for

public static double RoundUp(double input, int places)
{
    double multiplier = Math.Pow(10, Convert.ToDouble(places));
    return Math.Ceiling(input * multiplier) / multiplier;
}

Usage would look like:

RoundUp(189.182, 2);

This works by shifting the decimal point right 2 places (so it is to the right of the last 8) then performing the ceiling operation, then shifting the decimal point back to its original position.

MikeBaker
  • 770
  • 6
  • 4
  • 14
    This solution is technically incorrect. A double value has a mantissa and an exponent, and the exponent is of base 2, not base 10. Multiplying a double by 10 or 100 does not simply move a decimal point. The result after multiplication has a different bit pattern. That result may not fit in the mantissa with full precision as a binary number and may end up being truncated, in which case the last significant bit ends up being rounded based on some rules. – tomosius Apr 14 '15 at 23:06
  • 1
    but for a number like `189.182` you should be pretty safe. perhaps should case to a decimal? – Simon_Weaver Apr 06 '16 at 18:29
  • 5
    Simple case where this fails for decimal https://dotnetfiddle.net/6IeRVG Input 283.79, output 283.8 – fiat Sep 13 '18 at 01:43
  • 1
    Please pay attention to the warnings above. This method does produce unexpected results for certain numbers. – userSteve Sep 24 '18 at 13:15
34

You can use:

decimal n = 189.182M;
n = System.Math.Ceiling (n * 100) / 100;

An explanation of the various rounding functions can be found here.


Be aware that formulae like this are still constrained by the limited precision of the double type, should that be the type you are using (your question stated decimal but it's possible you may just have meant a floating point value with fractional component rather than that specific type).

For example:

double n = 283.79;
n = System.Math.Ceiling (n * 100);

will actually give you 28380, not the 283.79 you would expect(a).

If you want accuarate results across the board, you should definitely be using the decimal type.


(a) This is because the most accurate IEEE754 double precision representation of 283.79 is actually:

 283.790000000000020463630789891

That extra (admittedly minuscule) fractional component beyond the .79 gets ceilinged up, meaning it will give you a value higher than you would expect.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    This should be the accepted answer, as the current accepted answer does not address important floating point precision issues. – Ben Wilde Jun 25 '19 at 20:23
8

In .NET Core 3.0 and later versions, three additional rounding strategies are available through the MidpointRounding enumeration. Besides MidpointRounding.AwayFromZero and MidpointRounding.ToEven it now includes:

 1. MidpointRounding.ToNegativeInfinity
 2. MidpointRounding.ToPositiveInfinity
 3. MidpointRounding.ToZero

For this specific question you need to use MidpointRounding.ToPositiveInfinity, this will round the number up always. Note this only works if the number isn't negative. See table below for examples.

Original number ToNegativeInfinity ToPositiveInfinity ToZero
3.55 3.5 3.6 3.5
2.83 2.8 2.9 2.8
2.54 2.5 2.6 2.5
2.16 2.1 2.2 2.1
-2.16 -2.2 -2.1 -2.1
-2.54 -2.6 -2.5 -2.5
-2.83 -2.9 -2.8 -2.8
-3.55 -3.6 -3.5 -3.5

For more information about midpointrounding see https://learn.microsoft.com/en-us/dotnet/api/system.midpointrounding

And of course the code to make it work:

// function explained: Math.Round(number, amount of decimals, MidpointRounding);
decimal number = 189.182m;
number =  Math.Round(number, 2, MidpointRounding.ToPositiveInfinity);
// result: number = 189.19
Raoul
  • 188
  • 2
  • 8
5
            var numberToBeRound1 = 4.125;
            var numberToBeRound2 = 4.175;
            var numberToBeRound3 = 4.631;
            var numberToBeRound4 = 4.638;
            var numberOfDecimalPlaces = 2;
            var multiplier = Math.Pow(10, numberOfDecimalPlaces);

            //To Round Up => 4.13
            var roundedUpNumber = Math.Ceiling(numberToBeRound1 * multiplier) / multiplier;

            //To Round Down => 4.12
            var roundedDownNumber = Math.Floor(numberToBeRound1 * multiplier) / multiplier;

            //To Round To Even => 4.12
            var roundedDownToEvenNumber = Math.Round(numberToBeRound1, numberOfDecimalPlaces, MidpointRounding.ToEven);

            //To Round To Even => 4.18
            var roundedUpToEvenNumber = Math.Round(numberToBeRound2, numberOfDecimalPlaces, MidpointRounding.ToEven);

            //To Round To Away From Zero => 4.63
            var roundedDownToAwayFromZero = Math.Round(numberToBeRound3, numberOfDecimalPlaces, MidpointRounding.AwayFromZero);

            //To Round To Away From Zero => 4.64
            var roundedUpToAwayFromZero2 = Math.Round(numberToBeRound4, numberOfDecimalPlaces, MidpointRounding.AwayFromZero);
Furkan Öztürk
  • 1,178
  • 11
  • 24
4

How about

0.01 * ceil(100 * 189.182)
Itamar Katz
  • 9,544
  • 5
  • 42
  • 74
  • awesome, just what I needed. I dont know why but Math.ceil(189.182 * 100) / 100 doesnt work.... – Kevin Vella Jul 23 '12 at 12:54
  • Just want to add for anyone else who comes across this that to get more or less decimal places adjust the number of zeros in the constants - 3 decimal places is 0.001 * ceil(1000 * n) 4 is 0.0001 * ceil(10000 * n) and so on – Robin French May 12 '22 at 13:44
1
    public static decimal RoundUp(decimal input, int places)
    {
        decimal multiplier = (decimal)Math.Pow(10, places);
        return decimal.Ceiling(input * multiplier) / multiplier;
    }
0
   // Double will return the wrong value for some cases. eg: 160.80
    public static decimal  RoundUp(decimal input, int places)
    {
        decimal multiplier = Convert.ToDecimal(Math.Pow(10, Convert.ToDouble(places)));
        return Math.Ceiling(input * multiplier) / multiplier;
    }
Mahbub
  • 1
  • Please always describe what you are doing in your answer. It should be updated or removed. Read [How to answer](https://stackoverflow.com/help/how-to-answer) before you provide more answers ^^ – finnmglas Jul 26 '20 at 11:36
0

One other quirky but fun way to do it is Math.Round() after offsetting the number.

decimal RoundUp(decimal n, int decimals)
{
    n += decimal.Parse($"1e-{decimals}", System.Globalization.NumberStyles.AllowExponent) / 2;
    n -= 1e-28m;
    return Math.Round(n, decimals);
}
decimal RoundDown(decimal n, int decimals)
{
    n -= decimal.Parse($"1e-{decimals}", System.Globalization.NumberStyles.AllowExponent) / 2;
    n += 1e-28m;
    return Math.Round(n, decimals);
}

Is has the advantage of not using Math.Pow() which uses double and thus can cause unpredictable rounding errors.

This solution basically uses the fact that midpoint rounding can be turned into up/down rounding if you increase/decrease the number a little:

  • Math.Round(3.04m, 1) is 3.0 - not what we want
  • Let's add 0.04(9) to it
  • Math.Round(3.0899999999999999999999999999m, 1) is 3.1 - success!

Subtracting 1e-28m (= 0.0000000000000000000000000001) is important, because we want to be able to round up 3.0000000000000000000000000001 to 4, but 3.0000000000000000000000000000 should stay 3.

Robert Synoradzki
  • 1,766
  • 14
  • 20