【问题标题】:Rounding down to 2 decimal places in c#在c#中四舍五入到小数点后2位
【发布时间】:2012-11-23 01:26:12
【问题描述】:

如何将两位小数相乘并将结果四舍五入到小数点后两位?

例如,如果等式为 41.75 x 0.1,则结果将为 4.175。如果我在 c# 中使用小数执行此操作,它将自动舍入到 4.18。我想四舍五入到 4.17。

我尝试使用 Math.Floor,但它只是四舍五入到 4.00。这是一个例子:

Math.Floor (41.75 * 0.1);

【问题讨论】:

  • 你试过Math.Round吗?
  • 如果你想要四舍五入,你可以使用 Math.Round 的重载来控制如何处理中点。如果您一直想要地板,请考虑乘以 100,地板,然后除以 100。
  • 您想要 4.176 及更高版本的标准舍入吗?
  • 我刚刚在 LINQPad 中尝试过这个,当我将 41.75 乘以 0.1 时得到 4.175。我尝试使用小数和双数。
  • 对不起,它的意思是 41.75 * 0.1

标签: c# decimal rounding


【解决方案1】:

Math.Round(...) 函数有一个 Enum 来告诉它使用什么舍入策略。不幸的是,这两个定义并不完全适合您的情况。

两种中点舍入模式是:

  1. AwayFromZero - 当一个数字介于其他两个数字之间时,它会向离零最近的数字四舍五入。 (又名,四舍五入)
  2. ToEven - 当一个数字在其他两个数字之间时,它会向最接近的偶数四舍五入。 (0.16 优于 0.17,0.18 优于 0.17)

您要使用的是 Floor 和一些乘法。

var output = Math.Floor((41.75 * 0.1) * 100) / 100;

output 变量现在应该有 4.17。

其实你也可以写一个函数来获取可变长度:

public decimal RoundDown(decimal i, double decimalPlaces)
{
   var power = Convert.ToDecimal(Math.Pow(10, decimalPlaces));
   return Math.Floor(i * power) / power;
}

【讨论】:

  • 实际上,它应该使用Math.Round Method (Decimal, Int32, MidpointRounding)重载(检查stackoverflow.com/questions/13522095/…
  • i * power 是一个错误。你的意思是可能有两倍。
  • 你不能将双精度数与小数相乘
  • MidpointRounding 重载可以解决 0.5 舍入而不是向上舍入的问题(如果有一个名为“TowardZero”的策略),但我相信提问者举了一个糟糕的例子。他们的问题表明他们希望所有数字都向下舍入到 2 位数。所以 4.179999999 就是 4.17。如果您只希望中点向下舍入,则应使用该重载,但如果您希望全部向下舍入,则需要上述技术或其他答案中的类似技术。
  • 这几乎是 8 年前的事了。这仍然是最佳答案吗?
【解决方案2】:
public double RoundDown(double number, int decimalPlaces)
{
     return Math.Floor(number * Math.Pow(10, decimalPlaces)) / Math.Pow(10, decimalPlaces);
}

【讨论】:

  • 注意!根据设备的不同,这可能会导致准确性问题。当尝试将此函数应用于小数点后 2 位的值 10.40 时,我在使用 Xamarin 的 Android 设备上得到了 10.39。
【解决方案3】:

.NET Core 3.0 和即将推出的.NET Framework 5.0 开始,以下内容有效

Math.Round(41.75 * 0.1, 2, MidpointRounding.ToZero)

【讨论】:

  • 我很犹豫是否要使用它,因为我阅读的文档描述了“两个其他之间的数字 halfway”,但这确实可以正确回答问题,具体取决于您想要否定的内容。也可以考虑 ToNegativeInfinity
【解决方案4】:

c# 中没有对 Precision floor/ceillin 的原生支持。

但是,您可以通过将数字乘以底数来模拟该功能,然后除以相同的乘数。

例如,

decimal y = 4.314M;
decimal x = Math.Floor(y * 100) / 100;  // To two decimal places (use 1000 for 3 etc)
Console.WriteLine(x);  // 4.31

不是理想的解决方案,但如果数量很少,应该可以工作。

【讨论】:

    【解决方案5】:

    另一种解决方案是从从零舍入到零舍入。 应该是这样的:

        static decimal DecimalTowardZero(decimal value, int decimals)
        {
            // rounding away from zero
            var rounded = decimal.Round(value, decimals, MidpointRounding.AwayFromZero);
    
            // if the absolute rounded result is greater 
            // than the absolute source number we need to correct result
            if (Math.Abs(rounded) > Math.Abs(value))
            {
                return rounded - new decimal(1, 0, 0, value < 0, (byte)decimals);
            }
            else
            {
                return rounded;
            }
        }
    

    【讨论】:

      【解决方案6】:

      这是我的 Float-Proof Round Down。

          public static class MyMath
      {
          public static double RoundDown(double number, int decimalPlaces)
          {
              string pr = number.ToString();
              string[] parts = pr.Split('.');
              char[] decparts = parts[1].ToCharArray();
              parts[1] = "";
              for (int i = 0; i < decimalPlaces; i++)
              {
                  parts[1] += decparts[i];
              }
              pr = string.Join(".", parts);
              return Convert.ToDouble(pr);
          }
      }
      

      【讨论】:

        【解决方案7】:

        我发现最好的方法是使用字符串;数学的二进制变幻莫测往往会出错,否则。等待 .Net 5.0 使这一事实过时。没有小数位是一种特殊情况:您可以为此使用 Math.Floor。否则,我们 ToString 比所需的小数位多一位的数字,然后解析没有最后一位的数字以获得答案:

        /// <summary>
        /// Truncates a Double to the given number of decimals without rounding
        /// </summary>
        /// <param name="D">The Double</param>
        /// <param name="Precision">(optional) The number of Decimals</param>
        /// <returns>The truncated number</returns>
        public static double RoundDown(this double D, int Precision = 0)
        {
          if (Precision <= 0) return Math.Floor(D);
          string S = D.ToString("0." + new string('0', Precision + 1));
          return double.Parse(S.Substring(0, S.Length - 1));
        }
        

        【讨论】:

          【解决方案8】:

          如果您想将任何双精度数四舍五入到特定的小数位,如果中点无关紧要,您可以使用:

              public double RoundDownDouble(double number, int decimaPlaces)
              {
                  var tmp = Math.Pow(10, decimaPlaces);
                  return Math.Truncate(number * tmp) / tmp;
              }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-01-03
            • 2014-09-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-24
            • 2012-03-11
            • 1970-01-01
            相关资源
            最近更新 更多