如何在c#中使100.02f - 100 == 0.02f为真

本文关键字:02f 为真 中使 | 更新日期: 2023-09-27 18:10:22

似乎是舍入问题。我有一个float[]数组和对这个数组的一些操作。我需要为这个功能编写单元测试,但是考虑到这个舍入问题,比较期望值和结果值并不是一项简单的任务。是否有任何解决方法来测试我的数组上的数学运算?由于

如何在c#中使100.02f - 100 == 0.02f为真

舍入问题是浮点计算的固有部分。也许可以使用小数数组(decimal[]) ?

100.02m - 100

在单元测试中使用浮点数或双精度时,您的测试框架可能允许您考虑可接受的增量。例如,使用NUnit,你可以写

double expected = 1d;
double delta = 0.0001d;
double actual = classUnderTest.Method();
Assert.AreEqual(expected, actual, delta);

理解浮点型和双精度型对于某些事情本质上是不精确的,这是设计上的。它们表示以2为基数的数字。如果您需要精确的十进制表示,请使用相应的类型:decimal

如果你写了1.1 - 0.1 == 1.0,它仍然会返回false。这是因为你处理的是二进制数制中的浮点数。你不能精确地用二进制表示0.1,正如你不能精确地用十进制表示1/3。

在c#、Java、c++、C、JavaScript、Python和其他使用IEEE浮点标准的编程语言中都是如此。

您应该使用"epsilon"值来检查(其中epsilon由您选择)

if (yourvalue <= (0.02f + epsilon) && yourvalue >= (0.02f - epsilon))
    // do what you want

我不知道这是否已经在c#中实现了,这是"技术"方法

显然ε值应该足够小。另外,我建议编写一个扩展方法,以便在使用它时感觉更舒适

由于您正在编写单元测试,因此您可以轻松地计算出确切的输出。只需计算输出,然后使用"roundtrip"格式打印它,然后将该字符串粘贴到单元测试中:

float output = Operation(array);
Console.WriteLine(output.ToString("r"));

最后会得到Assert.AreEqual(100.02 - 100, 0.019999999999996)

或者,您可以将单元测试的输出转换为字符串,然后比较字符串。然后你会得到这样的结果:

Assert.AreEqual((100.02 - 100).ToString("f"), "0.02");

你不应该比较浮点数是否相等——你无法避免这种舍入错误。根据您的使用情况,如果您希望在像您这样的情况下更直观地四舍五入,则可以使用小数,或者将浮点数之间的差异与选择的"可接受的"错误值进行比较。