21

查看Convert.ToInt32()它的 msdn 文档指出:

如果 value 在两个整数的中间,则返回偶数;即4.5转换为4,5.5转换为6。

http://msdn.microsoft.com/en-us/library/ffdk7eyz.aspx

为什么是这样?

当然,四舍五入到最接近的整数会更合乎逻辑,不是吗?如果是这样的话,4.5 会变成 5,5.5 会变成 6,这似乎更直观。

4

4 回答 4

14

Rounding的维基百科条目的历史部分有一些关于“四舍五入”在计算中的作用的陈述。有趣的是,似乎“银行家四舍五入”几乎没有证据表明它在任何意义上都是官方的,因此只能被称为俚语。

如果您订阅该舍入机制,它只会“更合乎逻辑”。银行家四舍五入(在这种情况下是默认设置)也是完全合乎逻辑的。

想象一下,如果银行将每一小部分金额四舍五入到最接近的一美分,那么他们每天处理的数以百万计的交易将减少(损失很多,对于愤世嫉俗的人)的钱。好的,所以这个例子是愤世嫉俗的。

走向最接近的偶数(或奇数,但历史另有选择)意味着并非每个舍入分辨率都会上升现在有些可能会下降。当您将此应用于平均定律时,在考虑负责支付额外的半便士时,它成为一个公平的解决方案。

至于为什么选择它作为框架,这个问题试图解决它:

为什么.NET 默认使用银行家的四舍五入?

当然,这一切都可以追溯到金融时代,它对整数的适用性可能会受到质疑,但何必呢?接受它,如果你愿意,可以覆盖它,只要了解它是如何工作的。


对于想知道如何更改默认舍入的人:

如果您向您提供非整数,Convert.ToInt32则实际上首先需要执行类似的操作Convert.ToDouble,然后Math.Round使用重载来更改舍入逻辑

于 2012-07-11T11:40:30.080 回答
6

这正是将MidpontRounding重载添加到Math.Round.

因此,为了正确舍入,您应该使用 Math.Round 而不是 Convert.ToInt32。

于 2012-07-11T11:38:40.573 回答
3

不考虑 MidpointRounding.ToEven(银行家的舍入)或 MidpointRounding.AwayFromZero 是否是更好的默认值这一主观问题。

在设计这个时,微软会考虑 .NET 旨在取代的语言。

  • VB 经典一直默认使用银行家四舍五入法。

  • C / C++ 转换在强制转换时会截断,并且在运行时库中有库函数 floor() 和 ceil() - 但是(AFAIK,可能是错误的)没有轮函数。

  • Java 有一个 Math.round,在文档中被描述为等同于 Math.round(a+0.5)。这可能不是大多数人对负数的期望(-3.5 轮到 -3)。

  • 与来自 C/C++ 或 Java 的开发人员相比,VB 开发人员可能需要更多的支持。

因此,在设计 .NET 时,类库将提供和方法Floor,并且 Round 行为默认为 VB 的行为似乎是合理的。CeilingRound

Convert.ToInt32() 使用 Round 方法似乎也是合理的(尽管我想可以为 Floor 制作一个案例,以与铸造保持一致)。

于 2012-07-11T12:15:40.567 回答
2

如果您想要这种行为,您需要使用Math.Round并指定MidpointRounding.AwayFromZero.

例如:

int result = (int)Math.Round(4.5, MidpointRounding.AwayFromZero);

演示:http: //ideone.com/ZAbBL

Convert.ToInt32(double)不使用Math.Round自身,而是以这种方式实现(ILSpy):

public static int ToInt32(double value)
{
    if (value >= 0.0)
    {
        if (value < 2147483647.5)
        {
            int num = (int)value;
            double num2 = value - (double)num;
            if (num2 > 0.5 || (num2 == 0.5 && (num & 1) != 0))
            {
                num++;
            }
            return num;
        }
    }
    else
    {
        if (value >= -2147483648.5)
        {
            int num3 = (int)value;
            double num4 = value - (double)num3;
            if (num4 < -0.5 || (num4 == -0.5 && (num3 & 1) != 0))
            {
                num3--;
            }
            return num3;
        }
    }
    throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}
于 2012-07-11T11:43:20.543 回答