纵观MSDN文档Convert.ToInt32()
也指出:
如果值是中间两个整数之间,偶数则返回; 也就是说,4.5被转换为4,和5.5被转换为6。
http://msdn.microsoft.com/en-us/library/ffdk7eyz.aspx
为什么是这样?
当然,它会更合乎逻辑的四舍五入到最接近的整数,不是吗? 如果是这样,4.5将成为5和5.5将成为6,这似乎是更直观。
纵观MSDN文档Convert.ToInt32()
也指出:
如果值是中间两个整数之间,偶数则返回; 也就是说,4.5被转换为4,和5.5被转换为6。
http://msdn.microsoft.com/en-us/library/ffdk7eyz.aspx
为什么是这样?
当然,它会更合乎逻辑的四舍五入到最接近的整数,不是吗? 如果是这样,4.5将成为5和5.5将成为6,这似乎是更直观。
维基百科条目的历史部分四舍五入大约有作用的一些声明“轮,甚至”在计算。 有趣的是,它似乎“银行家舍入”有什么证据说明它是在这个词的任何意义上的官员,所以只能粉笔写的俚语术语。
只有“更符合逻辑”,如果您订阅的舍入机制。 银行家舍入(其在此情况下,默认)也是完全合乎逻辑的。
试想一下,如果银行调高为每一个分数量最接近的货币,他们会少了很多以百万计的交易,每天处理(失去很多,对于有争议的)钱数以百万计。 好了,这个例子是愤世嫉俗。
朝最近的偶数去(或奇数,但是历史选择了其他方式)意味着并不是每一个舍入分辨率上升 , 现在有人可以下去 。 当你把这个平衡法则,它成为一个公平的解决方案考虑谁是负责为多出的半便士支付时使用。
至于为什么这样选择的框架,这个问题试图解决这个问题:
为什么.NET使用银行家作为默认的舍入?
当然,这一切都可以追溯到金融天,其适用于整数号可能被质疑,但何必呢? 接受它,覆盖它,如果你想,才明白它是如何工作的。
如果你正在为一个非整数Convert.ToInt32
你首先真正需要做的是这样Convert.ToDouble
然后Math.Round
与超载改变舍入逻辑 。
这也正是为什么MidpontRounding
超载加入Math.Round
。
因此,对于正确的舍入你应该使用Math.Round而非Convert.ToInt32。
不考虑MidpointRounding.ToEven(银行家的舍入)或MidpointRounding.AwayFromZero是否会是一个更好的默认主观题。
在设计这一点,微软会考虑语言.NET的目的是要取代。
VB经典总是默认使用的银行家舍入。
C / C ++转换截断铸造时,具有库函数地板()和小区()在运行时库 - 但(AFAIK,可能是错误的)没有循环函数。
Java有一个Math.round该文档中被描述为等同于Math.round(A + 0.5)。 这无疑不是大多数人所期望的负数(-3.5两轮-3)。
VB开发人员可真可预计需要不是开发人员从C / C ++或Java的未来更手把手的指导。
因此,它似乎是合理的设计.NET时,类库将提供Floor
, Ceiling
和Round
的方法,以及在往返行为将默认为VB的行为。
这也似乎是合理的Convert.ToInt32()将使用Round方法(虽然我猜的情况下,可以为地面制成,一致性铸造)。
如果你想要的行为,你需要使用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"));
}