我在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
答案 0 :(得分:6)
只需拿出一个计算器并输入以下内容: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
现在通过使用Decimal类型更改Double类型,您的Assert应该可以正常工作。
答案 1 :(得分:2)
祝贺。您的单元测试实际上已经完成了他们应该做的事情,并且发现了您正在测试的代码的错误。
您有舍入错误。不幸的是,这是由您尝试单元测试的VB.NET代码而不是实际测试中的代码引起的。
您需要使用更精确的数据类型。我建议将Double
替换为Decimal
。
答案 2 :(得分:0)
您无法保证浮点数彼此相同,即使它们出现也是如此。
这取决于许多因素,如处理器,体系结构等。正如Justin所说,如果需要精度,请使用decimal。
看看Jon Skeets出色的博文:http://csharpindepth.com/Articles/General/FloatingPoint.aspx
答案 3 :(得分:0)
虽然其他海报是正确的,但您应该使用Decimal
代替Double
而不是导致观察到问题的原因。
观察到的问题是由舍入代码中的逻辑错误引起的。您需要查找如何正确舍入此类值。这是一个法律问题,而不是数学问题。
另一个奇怪的事情是你的CalculateRateBeforeTax
将其返回值四舍五入为一个整数值,但你发布的值似乎是在没有舍入的情况下计算的。