【问题标题】:.Net Rounding Issue.Net 舍入问题
【发布时间】:2011-04-27 13:09:05
【问题描述】:

我在 .Net 内部有一个舍入问题。

我将一个 3 位数的数字四舍五入为两位数,这会导致一个数字出现一些问题。

如果我尝试将 34.425 舍入到小数点后两位,它应该舍入到 34.43。我正在使用 roundawayfromzero 选项,它对程序中的每个数字都有效,除了这个。

代码 Math.Round(34.425, 2, MidpointRounding.AwayFromZero) 应该等于 34.43,但它等于 34.42。

如果我尝试使用任何其他号码,它会正常工作。

Math.Round(34.435, 2, MidpointRounding.AwayFromZero) = 34.44

Math.Round(34.225, 2, MidpointRounding.AwayFromZero) = 34.23

Math.Round(34.465, 2, MidpointRounding.AwayFromZero) = 34.47

我只是想看看有没有人遇到过这个问题?

目前我已通过将数字转换为小数来解决此问题。我已将代码更改为此,现在可以正常工作:

Math.Round(CDec(34.425), 2, MidpointRounding.AwayFromZero) = 34.43

我只是在寻找我的旧代码不起作用的原因。

谢谢!

将代码更新为正确的 AwayFromZero

【问题讨论】:

    标签: .net vb.net rounding


    【解决方案1】:

    浮点数从来都不是精确的,34.425 可能有一个内部表示 34.4249999999999.. 将四舍五入为 34.42。

    如果您需要精确表示数字,请使用 decimal 类型。

    【讨论】:

    • 感谢您的回复。我想我的大问题是为什么这对所有其他值都有效?
    • 如果它是一个变量,我也必须同意你的看法。但是,我将此值作为 34.425 放入观察列表。所以它不应该表示为 34.43499999 ......我的假设是否正确?
    • @Jeff:这是因为浮点表示。查看docs.sun.com/source/806-3568/ncg_goldberg.html 了解浮点数学的入门知识。基本上,浮点数以类似于科学记数法的形式存储,具有二进制基数/尾数和 2 指数的整数幂。并非所有数字都可以通过这种方式准确表示。小数虽然在大多数现实世界的算术中像浮点数一样工作,但使用略有不同的存储机制,它限制了可存储值的范围,但在该范围内大大提高了精度和准确度
    • +1 虽然可能是explained more precisely
    • 它的精确表示是 34.4249999999999971578290569595992565155029296875
    【解决方案2】:

    对于您实际使用的是MidpointRounding.ToEven 还是MidpointRounding.AwayFromZero 有点困惑。如果您使用 ToEven 作为第一个 sn-p 指示,这是预期的行为。

    【讨论】:

      【解决方案3】:

      您的假设和结果不正确:

      Math.Round(34.225, 2, MidpointRounding.ToEven) == 34.22
      Math.Round(34.465, 2, MidpointRounding.ToEven) == 34.46
      

      Math.Round(34.425, 2, MidpointRounding.ToEven) == 34.42
      

      这就是它的工作原理,这就是我在我的盒子上得到的。舍入到偶数的意思就是,向上或向下舍入到下一个感兴趣的小数位上的偶数。

      【讨论】:

      • 对不起,我复制了错误的代码。所有这些都应该是 AwayFromZero。
      • 这仅适用于感兴趣的小数点后的下一个小数点为 5,并且所有后续小数点均为零的情况。
      【解决方案4】:

      代码 Math.Round(34.425, 2, MidpointRounding.ToEven) 应该等于 34.43,但它等于 34.42。

      为什么? ToEven 必须使它成为 34.42,因为 42 是偶数。行为正确。

      【讨论】:

        【解决方案5】:

        我不使用 vb.net,所以我的推理可能不正确,但根据您的参数 MidpointRounding.ToEven 的名称,我预计 34.425 会四舍五入为 34.42;但我也希望 34.225 舍入到 34.22 和 34.465 到 34.46。在您的示例中以 5 结尾的数字四舍五入是一个约定问题。最常见的约定是四舍五入到偶数,我推断您的 .ToEven 参数将采用。

        此外,我怀疑您遇到了二进制/十进制舍入问题。检查 34.425 的二进制表示形式为 10010.011011....... 当您考虑十进制数(字节、字、双字、四字和负/正补码)的计算机存储和表示时,这可能会导致在你没有四舍五入你认为你的数字。

        要获得您想要的结果,您可能应该在四舍五入之前将 0.00001 添加到任何以 5 结尾的数字。

        【讨论】:

          猜你喜欢
          • 2013-04-12
          • 2011-08-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多