繁体   English   中英

为什么在比较两个双打时这个单元测试失败了?

[英]Why does this unit test fail when comparing two doubles?

我在vb.net中有以下代码来计算税前税额:

Public Shared Function CalculateRateBeforeTax(ByVal rate As Decimal, ByVal tax As Decimal) As Decimal
    Dim base As Decimal = rate / (1 + (tax / 100.0))
    Return Math.Round(base,2)
End Function

我设置的一些场景是:

费率= 107,税= 7%,基数= 100

费率= 325,税= 6.5%,基数= 305.16

费率= 215,税= 125%,基数= 95.55

我使用c#和使用nunit测试框架将上述场景放入一些单元测试中。 第一个场景通过,但另一个失败,我不知道如何让它通过。 这是我的测试:

[TestFixture]
class TaxTests
{
    [Test]
    public void CalculateRateBeforeTax_ShouldReturn100_WhenRateIs107AndTaxIs7Percent()
    {
        decimal expected = 100.0m;
        decimal actual = TaxUtil.CalculateRateBeforeTax(107.0m, 7.0m);

        Assert.AreEqual(expected,actual);
    }

    [Test]
    public void CalculateRateBeforeTax_ShouldReturn305point16_WhenRateIs325AndTaxIs6point5Percent()
    {
        decimal expected = 305.16m;
        decimal actual = TaxUtil.CalculateRateBeforeTax(325.0m, 6.5m);

        Assert.AreEqual(expected, actual);
    }

    [Test]
    public void CalculateRateBeforeTax_ShouldReturn95point55_WhenRateIs215AndTaxIs125Percent()
    {
        decimal expected = 95.55m;
        decimal actual = TaxUtil.CalculateRateBeforeTax(215.0m, 125.0m);

        Assert.AreEqual(expected, actual);
    }

}

正如我之前所说,第一次测试通过,但其他测试的结果是:

第二次测试预计305.1600000000000003d但是:305.1643192488263d

第三次测试预计95.54999999999997但是:95.55555555555555557d

只需拿出一个计算器并输入以下内容:325 /(1 +(6.5 / 100.0))

结果是305.164319 ...

然后你问305.164319 ......是否等于305.16。 测试显然失败了,他们的数字不一样。

现在,如果你想知道为什么你的数字略有不同,比如305.1600000000000003而不是305.16,这是因为Double类型有一些精度损失。 您可以使用Decimal类型以获得更高的精度。

但最重要的问题是CalculateRateBeforeTax返回的值没有被正确截断,以达到精确度。 你只需截断两个小数,如下所示:

Dim rounded As Decimal = Math.Floor(base * 100) / 100

现在通过改变Double类型的Decimal类型,您的Assert应该可以工作。

恭喜。 您的单元测试实际上已经完成了他们应该做的事情,并且发现了您正在测试的代码的错误。

你有舍入错误。 不幸的是,这是由您尝试单元测试的VB.NET代码而不是实际测试中的代码引起的。

您需要使用更精确的数据类型。 我建议替换你使用Double with Decimal

您无法保证浮点数彼此相同,即使它们看起来如此。

它取决于许多因素,如处理器,体系结构等。正如Justin所说,如果需要精度,请使用decimal。

看看Jon Skeets优秀博客文章: http//csharpindepth.com/Articles/General/FloatingPoint.aspx

虽然其他海报是正确的说明你应该使用Decimal而不是Double ,这不是你观察到的问题的原因。

观察到的问题是由舍入代码中的逻辑错误引起的。 您需要查找如何正确舍入此类值。 这是一个法律问题,而不是数学问题。

另一个奇怪的事情是你的CalculateRateBeforeTax其返回值四舍五入为一个整数值,但是你发布的值似乎是在没有舍入的情况下计算的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM