【问题标题】:Math.Round for even and odd numer in SilverlightSilverlight 中偶数和奇数的 Math.Round
【发布时间】:2014-02-18 06:01:09
【问题描述】:

我使用Math.Round 就像Math.Round(value, precision)。精度为 3。

当我使用 value = 0.0015 时,结果将是 0.002

当我使用 value = 0.0025 时,结果仍然是 0.002

好像最后一位为偶数时会向下取整,但最后一位为奇数时会向上取整。

如何解决这个问题?

补充:在silverlight中,没有MidpointRounding

【问题讨论】:

  • 您是在处理double 还是decimal 值? 0.00150.0025double 常量,但除非它们完全可表示,否则 double 不会有那个问题,只是会有不同的问题。

标签: c# silverlight math numbers rounding


【解决方案1】:

通过选择不同的舍入类型,请参阅http://msdn.microsoft.com/en-us/library/f5898377(v=vs.110).aspx

从那个链接:

using System;

public class Example
{
   public static void Main()
   {
      double[] values = { 2.125, 2.135, 2.145, 3.125, 3.135, 3.145 };
      foreach (double value in values)
         Console.WriteLine("{0} --> {1}", value, 
                           Math.Round(value, 2, MidpointRounding.AwayFromZero));

   }
}
// The example displays the following output: 
//       2.125 --> 2.13 
//       2.135 --> 2.13 
//       2.145 --> 2.15 
//       3.125 --> 3.13 
//       3.135 --> 3.14 
//       3.145 --> 3.15

更多信息:http://msdn.microsoft.com/en-us/library/system.midpointrounding(v=vs.110).aspx

正如评论员 2.135 --> 2.13 所指出的那样,它看起来不正确。这是因为浮点精度。原文指出:

由于表示可能导致精度损失 十进制值作为浮点数或执行算术 对浮点值的操作,在某些情况下是 Round(Double, Int32, MidpointRounding) 方法可能不会出现圆中点 由 mode 参数指定的值。这在图 以下示例,其中 2.135 舍入为 2.13 而不是 2.14。 发生这种情况是因为该方法在内部将值乘以 10 位,在这种情况下,乘法运算会受到 精度损失。

【讨论】:

  • 2.135 -> 2.13 在我看来并不像“远离零”。再说一次,我不认为 2.135 正好在 2.13m 和 2.14m 之间。
  • 那么我该如何舍入 2.135 --> 2.14 ??
  • @JohnNguyen MidpointRounding 会起作用,问题是 2.1349(等)在使用默认格式显示时可能会舍入到 2.135,但在正确舍入时会向下舍入到 2.13。
  • 对不起,但我还是没听懂你的意思。我需要从 2.135 到 2.14(等),但我尝试了 Math.Round(2.135, 2, MidpointRounding.AwayFromZero));Math.Round(2.135, 2, MidpointRounding.ToEven)); 它们都是 2.13
  • @JohnNguyen 我其实不知道,我深入研究了一下,无法证明错误。
【解决方案2】:

对于Decimals,你可以使用

Decimal RoundAwayFromZero(Decimal v)
{
    return Math.Truncate(v + (v < 0m ? -.5m : .5m));
}

Doubles 也一样:

Double RoundAwayFromZero(Double v)
{
    return Math.Truncate(v + (v < 0.0 ? -.5 : .5));
}

琐事:截断也可以用模表示 - 这里是Decimals:

Decimal Truncate(Decimal v)
{
    return v - (v % 1m);
}

对于在舍入前进行显式精度乘法的舍入,这里又是Decimals:

Decimal RoundAwayFromZero(Decimal v, Int32 p)
{
    var f = (Decimal)Math.Pow(10, p);

    return RoundAwayFromZero(v * f) / f;
}

【讨论】:

    【解决方案3】:

    我目前的解决方案是如下实现我的舍入方法。

        private double Rounding(double value, int Precision)
        {
            double result = value;
            if (result.ToString().EndsWith("5"))
            {
                var power = result.ToString().LastIndexOf("5") - 1;
                if (power > Precision)
                {
                    result = result + (1 / Math.Pow(10, power));
                }
            }
            result = Math.Round(result, Precision);
            return result;
        }
    

    【讨论】:

    • 在许多方面都令人恐惧和破碎。 :-) 如果数字大于 1 怎么办?更重要的是,.ToString() 本身已经进行了舍入,例如:Double.Parse( (5 / 9.0).ToString() ) &gt; 0.555555555555555555555556 给出了 true,即使它是 false。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-21
    • 1970-01-01
    相关资源
    最近更新 更多