查看Convert.ToInt32()
的msdn文档,它声明:
如果值在两个整数之间,则偶数为 回;也就是说,4.5转换为4,5.5转换为6.
http://msdn.microsoft.com/en-us/library/ffdk7eyz.aspx
为什么会这样?
当然,向最接近的整数舍入是更合乎逻辑的,不是吗?如果是这样,4.5将变为5,而5.5将变为6,这似乎更直观。
答案 0 :(得分:11)
维基百科Rounding条目的历史记录部分有一些关于“计算中的圆形”的作用的陈述。有趣的是,似乎“Bankers Rounding”几乎没有证据表明它在任何意义上都是官方的,因此只能用作俚语。
如果您订阅该舍入机制,那只是“更合乎逻辑”。四舍五入(在这种情况下是默认值)也是完全符合逻辑的。
想象一下,如果银行为每一小部分金额四舍五入到最接近的便士,那么每天处理的数百万交易就会减少很多(对于愤世嫉俗的人而言)损失很多钱。好的,所以这个例子是愤世嫉俗的。
走向最近的偶数(或奇数,但历史选择其他方式)意味着并非每个舍入分辨率上升,有些现在可以向下 < / strong>即可。当你把这个放到平均律时,当考虑 谁 负责支付额外的半便士时,它就成了一个公平的解决方案。
至于为什么选择这个框架,这个问题试图解决它:
Why does .NET use banker's rounding as default?
当然,这一切都可以追溯到金融时代,它对整数的适用性可能会受到质疑,但为什么要这么做呢?接受它,如果你想要覆盖它,只需了解它是如何工作的。
<小时/> 对于想知道如何更改默认舍入的人:
如果您向Convert.ToInt32
提供非整数,则首先需要执行Convert.ToDouble
然后Math.Round
with the overload to change the rounding logic之类的操作。
答案 1 :(得分:3)
这就是为MidpontRounding
添加Math.Round
重载的原因。
因此,为了正确舍入,您应该使用Math.Round而不是Convert.ToInt32。
答案 2 :(得分:3)
不考虑MidpointRounding.ToEven(Banker的舍入)或MidpointRounding.AwayFromZero是否是更好的默认值的主观问题。
在设计时,微软会考虑使用.NET设计替代的语言。
VB classic默认使用Banker的舍入。
C / C ++转换在转换时截断,并且在运行时库中具有库函数floor()和ceil() - 但是(AFAIK,可能是错误的)没有循环函数。
Java有一个Math.round,in the documentation被描述为等同于Math.round(a + 0.5)。这可能不是大多数人对负数的预期(-3.5轮到-3)。
可以说,VB开发人员可能需要比来自C / C ++或Java的开发人员更多的手持操作。
因此,在设计.NET时,类库将提供Floor
,Ceiling
和Round
方法似乎是合理的,并且Round行为将默认为VB的行为。
Convert.ToInt32()使用Round方法似乎也是合理的(虽然我想可以为Floor做一个案例,以便与cast一致)。
答案 3 :(得分:1)
如果您需要这种行为,则需要使用Math.Round
并指定MidpointRounding.AwayFromZero
。
例如:
int result = (int)Math.Round(4.5, MidpointRounding.AwayFromZero);
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"));
}