Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 为什么Math.Round(2.5)返回2而不是3?_.net_Rounding - Fatal编程技术网

.net 为什么Math.Round(2.5)返回2而不是3?

.net 为什么Math.Round(2.5)返回2而不是3?,.net,rounding,.net,Rounding,在C#中,Math.Round(2.5)的结果是2 应该是3,不是吗?为什么在C#?中是2,这被称为舍入到偶数(或银行家舍入),这是一种有效的舍入策略,可以最大限度地减少总和中的累积错误(middpointrounding.ToEven)。理论是,如果你总是在同一个方向上取整0.5个数字,那么误差会更快地累积(取整到偶数应该是为了最小化这一点)(a) 有关以下各项的MSDN说明,请访问以下链接: ,向负无穷大方向舍入 ,它向正无穷大进位 ,向上或向下舍入到零 ,它舍入到最接近的整数或指定的小数

在C#中,
Math.Round(2.5)
的结果是2


应该是3,不是吗?为什么在C#?

中是2,这被称为舍入到偶数(或银行家舍入),这是一种有效的舍入策略,可以最大限度地减少总和中的累积错误
(middpointrounding.ToEven)
。理论是,如果你总是在同一个方向上取整0.5个数字,那么误差会更快地累积(取整到偶数应该是为了最小化这一点)(a)

有关以下各项的MSDN说明,请访问以下链接:

  • ,向负无穷大方向舍入
  • ,它向正无穷大进位
  • ,向上或向下舍入到零
  • ,它舍入到最接近的整数或指定的小数位数。如果两种可能性之间的距离正好相等,则可以指定该行为,例如舍入使最后一个数字为偶数(
    舍入(2.5,中点舍入.ToEven)
    “变为2”)或使其远离零(
    舍入(2.5,中点舍入.AwayFromZero)
    “变为3”)
以下图表和表格可能会有所帮助:

-3        -2        -1         0         1         2         3
 +--|------+---------+----|----+--|------+----|----+-------|-+
    a                     b       c           d            e

                       a=-2.7  b=-0.5  c=0.3  d=1.5  e=2.8
                       ======  ======  =====  =====  =====
Floor                    -3      -1      0      1      2
Ceiling                  -2       0      1      2      3
Truncate                 -2       0      0      1      2
Round(ToEven)            -3       0      0      2      3
Round(AwayFromZero)      -3      -1      0      2      3
请注意,
Round
比它看起来强大得多,因为它可以舍入到特定的小数位数。所有其他的整数总是小数点零。例如:

n = 3.145;
a = System.Math.Round (n, 2, MidpointRounding.ToEven);       // 3.14
b = System.Math.Round (n, 2, MidpointRounding.AwayFromZero); // 3.15
对于其他函数,您必须使用乘法/除法技巧来实现相同的效果:

c = System.Math.Truncate (n * 100) / 100;                    // 3.14
d = System.Math.Ceiling (n * 100) / 100;                     // 3.15

(a) 当然,该理论取决于这样一个事实,即数据在偶数部分(0.5、2.5、4.5等)和奇数部分(1.5、3.5等)之间的值分布相当均匀

如果所有“一半值”都是偶数(例如),则错误累积的速度将与您总是四舍五入一样快。

来自MSDN:

默认情况下,Math.Round使用 中点四舍五入。大多数人 不熟悉“舍入到” 甚至“作为替代方案”,四舍五入 “远离零”更常见 在学校教书。净额默认为 按原样“四舍五入到相等” 统计上优越,因为它 不赞成 “从零开始四舍五入”到四舍五入 比它更频繁一些 向下(假设数字为 四舍五入往往是积极的。)


这篇文章有你想要的答案:

基本上是这样说的:

返回值

精度等于数字的最接近值的数字。如果值介于两个数字之间,其中一个是偶数,另一个是奇数,则返回偶数。如果值的精度小于位数,则返回的值将保持不变

该方法的行为遵循IEEE标准754第4节。这种四舍五入有时被称为四舍五入到最近值,或银行家四舍五入。如果数字为零,这种舍入有时称为向零舍入。

舍入的本质 考虑将包含分数的数字四舍五入为整数的任务。在这种情况下,舍入的过程是确定哪个整数最能代表要舍入的数字

public double ArithRound(double number,int places){

  string numberFormat = "###.";

  numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');

  return double.Parse(number.ToString(numberFormat));

}
通常,或“算术”四舍五入,很明显2.1、2.2、2.3和2.4四舍五入为2.0;及2.6,2.7,2.8及2.9至3.0

剩下的是2.5,与3.0相比,2.5更接近2.0。由您在2.0和3.0之间进行选择,两者都同样有效

对于负数,-2.1,-2.2,-2.3和-2.4,将变为-2.0;和-2.6、2.7、2.8和2.9在算术舍入下将变为-3.0

public double ArithRound(double number,int places){

  string numberFormat = "###.";

  numberFormat = numberFormat.PadRight(numberFormat.Length + places, '#');

  return double.Parse(number.ToString(numberFormat));

}
对于-2.5,需要在-2.0和-3.0之间进行选择

其他形式的舍入

“四舍五入”取任何带小数点的数字,并使其成为下一个“整数”。因此,不仅2.5和2.6轮到3.0,2.1和2.2轮也是如此

向上舍入使正数和负数都远离零。例如2.5到3.0和-2.5到-3.0

“向下舍入”通过切掉不需要的数字来截断数字。这会使数字向零移动。例如2.5到2.0和-2.5到-2.0

在最常见的“银行家四舍五入”形式中,要四舍五入的.5可以向上或向下四舍五入,因此四舍五入的结果始终是偶数。因此,2.5轮到2.0轮,3.5轮到4.0轮,4.5轮到4.0轮,5.5轮到6.0轮,依此类推

“交替舍入”在向下舍入和向上舍入之间交替任何.5的过程

“随机舍入”是在完全随机的基础上向上或向下舍入.5

对称和不对称

如果舍入函数将所有数字舍入到零或将所有数字舍入到零,则称舍入函数为“对称”

如果正数向零舍入,负数向零舍入,则函数是“不对称的”。。例2.5至2.0;和-2.5至-3.0

同样不对称的是一个函数,它将正数从零舍入,负数向零舍入。例2.5至3.0;和-2.5至-2.0


大多数情况下,人们会想到对称舍入,其中-2.5将被舍入到-3.0,3.5将被舍入到4.0。(在C
舍入(AwayFromZero)

首先,这无论如何都不是一个C#bug,它将是一个.NET bug。C#是一种语言,它不决定如何实现
Math.Round

第二,否-如果您阅读,您将看到默认舍入为“舍入到偶数”(银行家舍入):

返回值
类型:System.Double
最接近a的整数。如果 a的分数分量是一半 在两个整数之间,其中一个是 偶数和另一个奇数,然后是偶数 返回数字。请注意 方法返回一个
Double
,而不是 整型

备注
此方法的行为遵循IEEE标准754, 第4节。这种四舍五入的方法是不正确的 有时称为四舍五入到最近, 或银行家四舍五入。
public double RoundCorrect(double d, int decimals)
{
    double multiplier = Math.Pow(10, decimals);

    if (d < 0)
        multiplier *= -1;

    return Math.Floor((d * multiplier) + 0.5) / multiplier;

}
int roundedNumber = (int)Math.Floor(d + 0.5);
public double getRounding(double number, int decimalPoints)
{
    double decimalPowerOfTen = Math.Pow(10, decimalPoints);
    return Math.Floor(number * decimalPowerOfTen + 0.5)/ decimalPowerOfTen;
}
getRounding(239, -2) = 200
Public Function Round(number As Double, dec As Integer) As Double
    Dim decimalPowerOfTen = Math.Pow(10, dec)
    If CInt(number * decimalPowerOfTen) = Math.Round(number * decimalPowerOfTen, 2) Then
        Return Math.Round(number, 2, MidpointRounding.AwayFromZero)
    Else
        Return CInt(number * decimalPowerOfTen + 0.5) / 100
    End If
End Function
public enum MidpointRounding
{
    ToEven,
    AwayFromZero
}

public static class DecimalExtensions
{
    public static decimal Round(this decimal d, MidpointRounding mode)
    {
        return d.Round(0, mode);
    }

    /// <summary>
    /// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
    /// </summary>
    /// <param name="d">A Decimal number to be rounded.</param>
    /// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>
    /// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>
    public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
    {
        if ( mode == MidpointRounding.ToEven )
        {
            return decimal.Round(d, decimals);
        }
        else
        {
            decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
            int sign = Math.Sign(d);
            return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
        }
    }
}
public int Round(double value)
{
    double decimalpoints = Math.Abs(value - Math.Floor(value));
    if (decimalpoints > 0.5)
        return (int)Math.Round(value);
    else
        return (int)Math.Floor(value);
}
Math.Ceiling(decimal.Parse(yourNumber + ""));