【问题标题】:Truncating a number to specified decimal places将数字截断到指定的小数位
【发布时间】:2013-07-12 17:37:49
【问题描述】:

我需要将一个数字截断到小数点后 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 的错误。

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

【问题讨论】:

  • 0/100 不是除以 0 错误。这是0,这是您所期望的。
  • @sehe truncate != round
  • 是的。我注意到。但是,不能撤回投票。对不起
  • @Paolo Moretti:“根据 MSDN 将 d 舍入到最接近零的整数”。从技术上讲,虽然这种方法仍然是四舍五入,但没关系。

标签: c#


【解决方案1】:

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

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除,绝对安全。

【讨论】:

  • dam you beat me :) 只是在写同样的 math.truncate 示例,哈哈 +1。
  • Math.Truncate 和 Decimal.Truncate 有什么区别?我猜 Math.Truncate 是同一事物的静态(旧)版本。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    我同意 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;
    }
    

    【讨论】:

    • 我喜欢它。简单而优雅。 +1。
    【解决方案4】:

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

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

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

    【讨论】:

      【解决方案5】:
      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);
              }
              
          }
      

      【讨论】:

      • 一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-12
      • 1970-01-01
      • 2011-05-10
      • 1970-01-01
      • 2016-06-27
      • 2017-11-29
      相关资源
      最近更新 更多