13

我需要将一个数字截断到小数点后 2 位,这基本上意味着去掉多余的数字。

例如:

2.919     ->      2.91

2.91111   ->     2.91

为什么?这就是 SQL 服务器在存储多个特定精度时所做的事情。例如,如果一列是 Decimal(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
    

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

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

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

    我对此也不满意,因为如果 tooLongDecimal 为 0,我会得到除以 0 的错误。

当然有更好+更简单的方法!有什么建议么?

4

5 回答 5

8

你自己已经回答了这个问题;看来您只是误解了除以零的含义。正确的方法是乘法、截断、除法,如下所示:

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,这是完全安全的。

于 2013-07-14T22:30:48.170 回答
6

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

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

用法:

decimal value = 18446744073709551615.262626263m;
value = value.TruncateDecimal(6); // Result: 18446744073709551615.262626
于 2016-04-17T16:39:53.487 回答
3

我同意 pswg 我有类似的要求,这是我的经验和更通用的截断函数。

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;
}
于 2014-05-14T00:16:24.977 回答
1

使用decimal.ToString('0.##') 强制舍入:

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

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

于 2013-07-14T22:31:55.550 回答
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);
        }
        
    }
于 2020-09-19T14:56:33.883 回答