MS Test中的double.NaN相等性

6
为什么我会得到这个结果?
[TestMethod]
public void nan_test()
{
    Assert.AreEqual(1, double.NaN, 1E-1); <-- Passes
    Assert.AreEqual(1, double.NaN);       <-- Fails
}

delta对于判断NaN是否等于一个数字有什么不同之处?它应该总是返回false。我知道IsNaN,但在这里没有用(请参见下文)。

背景:我有一个函数返回NaN(错误的),本来应该是一个实数,但测试仍然通过了。我使用delta是因为它是双精度相等性,原始测试使用1E-9。


2
微软错误记录:https://connect.microsoft.com/VisualStudio/feedback/details/762286/unit-test-with-assert-areequal-2-3-double-nan-0-1-passes - jbe
请参见https://dev59.com/1nI-5IYBdhLWcg3wlpaW - Colonel Panic
可能是重复的问题:为什么Assert.AreEqual(1.0,double.NaN,1.0)通过? - TamaMcGlinn
3个回答

4
当您使用Assert.AreEqual(1, double.NaN)时,它会尝试对数字进行相等性测试,但是它失败了,因为double.NaN不等于任何东西。
当您执行Assert.AreEqual(1, double.NaN, 1E-1)时,它必须对数字进行算术运算。具体来说,它计算
Math.Abs((double) (expected - actual)) > delta
Math.Abs(1 - double.NaN) > 1E-1
Math.Abs(double.NaN) > 1E-1 // All arithmetic with double.NaN returns double.NaN
double.NaN > 1E-1 // All comparisons with double.NaN return false (except !=)

这是错误的。它看起来实际上的delta并没有比你传递的delta更大,但只是因为它试图表明你不能执行比较。

故事的寓意:NaN的行为非常疯狂(但是一些聪明人能想出的最好的方法)。在执行任何计算之前,请尽力检查NaN是否存在,特别是像这样无法将错误静默传播的计算。


2

你能否使用这个测试来判断 NaN 吗?

double.IsNaN(somenNumber)

1
是的,但我不希望我的结果是NaN,如果我只是在没有调试的情况下运行测试并期望一个值,那么它会通过。这不好。 - RichK

2
请看这里:为什么Assert.AreEqual(1.0, double.NaN, 1.0)通过了测试? 编辑: Assert.AreEqual中肯定存在一个错误。在VS 2008的Microsoft.VisualStudio.QualityTools.UnitTestFramework中,它被编码为:
if (Math.Abs((double) (expected - actual)) > delta)
{
    // report error
}

就像你的情况一样,Math.Abs((double) (expected - actual)) 是一个 double.NaN,所以比较结果为 false :-)


太好了,谢谢。那个问题的 OP 似乎和我做了完全相同的事情,很奇怪。 - RichK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接