将数字截断到指定的小数位

时间:2013-07-14 22:18:11

标签: c#

我需要将一个数字截断为2位小数,这基本上意味着 砍掉额外的数字。

例如:

2.919     ->      2.91

2.91111   ->     2.91

为什么呢?这是SQL服务器在存储多个a时所做的事情 特别精确。例如,如果列是十进制(8,2),并且您尝试 插入/更新9.1234的数字,3和4将被切断。

我需要在c#代码中做同样的事情。

我能想到的唯一可行方法是:

  1. 使用stringformatter仅“打印”出来 两位小数,然后将其转换为小数,      例如:

      decimal tooManyDigits = 2.1345
    
    decimal ShorterDigits = Convert.ToDecimal(tooManyDigits.ToString("0.##"));
    
    // ShorterDigits is now 2.13
    

    我对此并不满意,因为它涉及一个to-string然后 另一个字符串到十进制转换似乎有点疯狂。

  2. 使用Math.Truncate(只接受整数),所以我 可以将它乘以100,截断它,然后除以100.例如:

    decimal tooLongDecimal = 2.1235;
    
    tooLongDecimal = Math.Truncate(tooLongDecimal * 100) / 100;
    

    我对此也不满意,因为如果tooLongDecimal是0, 我会得到0分之差。

  3. 肯定有更好的+更简单的方法!有什么建议吗?

5 个答案:

答案 0 :(得分:5)

你自己回答了这个问题;你似乎只是误解了零除的意思。这样做的正确方法是乘法,截断,然后分开,如下所示:

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

这里没有除零,只有除以100,这是完全安全的。

答案 1 :(得分:3)

以前提供的数学解决方案很容易因大量数字和/或大量小数位而溢出。请考虑以下扩展名:

[System.Runtime.CompilerServices.Extension()]
public static decimal TruncateDecimal(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 = Math.Pow(10, decimals);

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

        return integerPart + scalingFactor;
    }
}

用法:

decimal value = 18446744073709551615.262626263m;
value = value.TruncateDecimal(6);

答案 2 :(得分:1)

我同意p.s.w.g.我有类似的要求,这是我的经验和截断的更广义的功能。

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;
}

答案 3 :(得分:0)

使用decimal.ToString('0.##') 强加四舍五入:

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

(是的,可能应该是一个评论,但这样很难格式化。)

答案 4 :(得分:0)

public static decimal Rounding(decimal val, int precision)
    {
        decimal res = Trancating(val, precision + 1);
        return Math.Round(res, precision, MidpointRounding.AwayFromZero);
    }
    public static decimal Trancating(decimal val,int precision)
    {
        if (val.ToString().Contains("."))
        {
            string valstr = val.ToString();
            string[] valArr = valstr.Split('.');
            if(valArr[1].Length < precision)
            {
                int NoOfZeroNeedToAdd = precision - valArr[1].Length;
                for (int i = 1; i <= NoOfZeroNeedToAdd; i++)
                {
                    valstr = string.Concat(valstr, "0");
                }
            }
            if(valArr[1].Length > precision)
            {
                valstr = valArr[0] +"."+ valArr[1].Substring(0, precision);
            }
            return Convert.ToDecimal(valstr); 
        }
        else
        {
            string valstr=val.ToString();
            for(int i = 0; i <= precision; i++)
            {
                    if (i == 1)
                        valstr = string.Concat(valstr, ".0");
                    if(i>1)
                    valstr = string.Concat(valstr, "0");
            }
            return Convert.ToDecimal(valstr);
        }
        
    }