【问题标题】:Why does Convert.ToInt32() round to the nearest even number, instead of nearest whole number? [closed]为什么 Convert.ToInt32() 舍入到最接近的偶数,而不是最接近的整数? [关闭]
【发布时间】:2012-07-11 11:35:54
【问题描述】:

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

如果值在两个整数的中间,则偶数是 回来;即4.5转4,5.5转6。

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

这是为什么?

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

【问题讨论】:

  • 如果您想要特定的行为,请使用Math.Round 方法。当然,Convert.ToInt32() 确实已经在描述的行为中使用了这种方法。它与平均值有关,您转换并添加 6 个数字,其中一半向下舍入,另一半向上舍入,如果所有内容都向上舍入或向下舍入,您会得到更准确的数字。
  • @Ramhound 我很欣赏这一点,我只是好奇为什么在任何情况下甚至都偏爱奇数
  • 当你说“当然,四舍五入到最接近的整数会更合乎逻辑?”,整个问题是有两个'最接近的整数'.. .
  • @Curt 我认为这通常是因为大多数学校(至少在英格兰)只教授四舍五入,其中 0.5 表示“上升”。我陷入了“这到底是怎么回事?”银行家四舍五入的陷阱。

标签: c# decimal rounding int32


【解决方案1】:

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

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

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

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

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

Why does .NET use banker's rounding as default?

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


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

如果您向Convert.ToInt32 提供非整数,您实际上首先需要执行Convert.ToDouble 之类的操作,然后是Math.Round with the overload to change the rounding logic

【讨论】:

  • 我认为你的意思是银行会赚更少的钱……我无法想象他们会失去任何东西
  • @musefan 但在银行业,赚的少不等于亏了?你也在这个国家,你应该和我一样对银行抱有愤世嫉俗的态度,哈哈
  • @AdamHouldsworth 谢谢亚当,我以前没有听说过银行家四舍五入,这有助于消除我的困惑。
  • @musefan - 但他们实际上并没有赚到更少的钱,在大多数情况下,我们说的是一分钱的一半,如果你把所有交易平均起来,那么平均来说你至少交易。在制作这些 cmets 之前,您应该参加一些会计课程。
  • @Ramhound:关于亚当的评论是个笑话……也许你应该参加一些阅读课程;)
【解决方案2】:

这正是MidpontRounding 重载被添加到Math.Round 的原因。

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

【讨论】:

  • 嗯……你自己和其他人似乎对这个问题感到困惑。我没有看到任何部分说“我怎样才能获得一致性?”,这更多是关于为什么首先做出决定。我也同意,如果有目的地这样做,这不是一个很好的默认行为
  • @Ramhound Possibly not.
  • @AdamHouldsworth - 这不会使它成为一个重复的问题
  • @Ramhound 在检查中是的,但是在为重复检测机器提供少量重复时有一些价值。输入上述问题时,搜索结果中永远不会返回有问题的重复项。
【解决方案3】:

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

在设计时,Microsoft 会考虑 .NET 旨在取代的语言。

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

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

  • Java 有一个 Math.round,in the documentation 被描述为等效于 Math.round(a+0.5)。这可以说不是大多数人对负数的期望(-3.5 轮到 -3)。

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

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

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

【讨论】:

    【解决方案4】:

    如果您想要这种行为,您需要使用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"));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-17
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      • 2011-03-21
      相关资源
      最近更新 更多