【问题标题】:Divide By Zero Oddities除以零奇数
【发布时间】:2013-02-23 08:28:46
【问题描述】:

我今天遇到了一个问题,我不小心被零除,但没有抛出异常。当我使用调试器时,我在调试器中看到了“NaN”。当我尝试用 NUnit 重新创建这个场景时,Assert 说我正在返回“Infinity”。不能完全让调试器显示 NaN,但我只是想知道为什么在这种情况下没有抛出错误?我花了很长时间才找到这个问题,我会认为应该抛出异常?

这里是测试代码:

public class DivideByZero {

    private int TotalQaOneToFour;
    private int TotalGrade = 10;

    public DivideByZero(int TotalQaOneToFour) {
      this.TotalQaOneToFour = TotalQaOneToFour;
    }

    public Double QualityReportAverageRounded {
      get {
        return Math.Round((double)TotalGrade / TotalQaOneToFour, 2);
      }
    }
  }


  [TestFixture]
  public class DivideByZeroTest {

    [Test]
    public void TestThatDivideByZeroThrowsWhenUsingMathRound() {

      var dbz = new DivideByZero(0);

      Assert.AreEqual(0, dbz.QualityReportAverageRounded);
    }

  }

这是 NUnit 输出:

测试'DivideByZeroTest.TestThatDivideByZeroThrowsWhenUsingMathRound' 失败:
预期:0
但是是:无限
除零.cs(33,0):在 DivideByZeroTest.TestThatDivideByZeroThrowsWhenUsingMathRound()

0 次通过,1 次失败,0 次跳过,耗时 0.41 秒 (NUnit 2.6.1)。

【问题讨论】:

标签: c#


【解决方案1】:

浮点数除以零,就像你在这里看到的那样,会导致无穷大或非数 (NaN)。整数除以零会导致异常。

将非零值除以零时会产生无穷大。当您将零除以零时会产生 NaN。

【讨论】:

    【解决方案2】:

    无法让调试器显示 NaN,但我只是想知道为什么在这种情况下没有抛出错误?

    因为这会违反规范 :) 基本上,这里不需要抛出异常,因为 IEEE-754 a) 定义了如何处理除以 0; b) 对除以 0 的结果具有适当的值。对于整数类型(和 decimal),这些都不是正确的,这是你得到 DivideByZeroException 的地方。

    如果你将任何非零、非 NaN 值除以零,你应该得到无穷大(正或负)。如果你将零(或 NaN)除以零,你应该得到 NaN。

    示例代码:

    using System;
    
    class Test
    {
        static void Main()
        {
            // Prevent everything being computed at compile-time
            double zero = 0d;
            Console.WriteLine(1d / zero);  // Infinity
            Console.WriteLine(0d / zero);  // NaN
            Console.WriteLine(-1d / zero); // -Infinity
        }
    }
    

    来自 C# 5 规范第 7.8.2 节(其他编号适用于其他版本):

    整数除法

    [...]
    如果右操作数的值为零,则抛出 System.DivideByZeroException。
    [...]

    浮点除法

    商是根据 IEEE 754 算术规则计算的。下表列出了非零有限值、零、无穷大和 NaN 的所有可能组合的结果。

    (然后有一个表格给出了与我之前描述的相同类型的结果。)

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-16
    • 1970-01-01
    相关资源
    最近更新 更多