Truncating a number to specified decimal places

The previously offered mathematical solutions are vulnerable to overflow with large numbers and/or a large number of decimal places. Consider instead the following extension method:

public static decimal TruncateDecimal(this decimal d, int decimals)
{
    if (decimals < 0)
        throw new ArgumentOutOfRangeException("decimals", "Value must be in range 0-28."); 
    else if (decimals > 28)
        throw new ArgumentOutOfRangeException("decimals", "Value must be in range 0-28.");
    else if (decimals == 0)
        return Math.Truncate(d);
    else
    {
        decimal integerPart = Math.Truncate(d);
        decimal scalingFactor = d - integerPart;
        decimal multiplier = (decimal) Math.Pow(10, decimals);

        scalingFactor = Math.Truncate(scalingFactor * multiplier) / multiplier;

        return integerPart + scalingFactor;
    }
}

Usage:

decimal value = 18446744073709551615.262626263m;
value = value.TruncateDecimal(6); // Result: 18446744073709551615.262626

Using decimal.ToString('0.##') also imposes rounding:

1.119M.ToString("0.##")  // -> 1.12

(Yeah, likely should be a comment, but it's hard to format well as such.)


I agree with p.s.w.g. I had the similar requirement and here is my experience and a more generalized function for truncating.

http://snathani.blogspot.com/2014/05/truncating-number-to-specificnumber-of.html

public static decimal Truncate(decimal value, int decimals)
{
    decimal factor = (decimal)Math.Pow(10, decimals);
    decimal result = Math.Truncate(factor * value) / factor;
    return result;
}

You've answered the question yourself; it seems you just misunderstood what division by zero means. The correct way to do this is to multiply, truncate, then devide, like this:

decimal TruncateTo100ths(decimal d)
{
    return Math.Truncate(d* 100) / 100;
}

TruncateTo100ths(0m);       // 0
TruncateTo100ths(2.919m);   // 2.91
TruncateTo100ths(2.91111m); // 2.91
TruncateTo100ths(2.1345m);  // 2.13

There is no division by zero here, there is only division by 100, which is perfectly safe.

Tags:

C#