我有一套 240 个具有不同抽头数的 FIR 滤波器卷积单元测试。
所有测试都通过了,当我正在完善时,我注意到比较的增量是
1E-04f
。
我将其降低到
1E-05f
,有效,尝试过1E-06f
,但通过率是< 50% then.
1E-05f 示例:
index expected actual difference match
0 -2.7051452E-34 -2.7051452E-34 0.000000E+000 True
1 0.00011297482 0.00011297482 0.000000E+000 True
2 0.00022594964 0.00022594964 0.000000E+000 True
3 -0.0010179491 -0.0010179491 0.000000E+000 True
4 -0.0022618477 -0.0022618477 0.000000E+000 True
5 0.0019123415 0.0019123415 0.000000E+000 True
6 0.00608653 0.00608653 0.000000E+000 True
7 -0.0052014478 -0.0052014478 0.000000E+000 True
8 -0.016489426 -0.016489424 1.862645E-009 True
9 0.009599558 0.009599558 0.000000E+000 True
10 0.035688534 0.035688538 3.725290E-009 True
11 -0.026160091 -0.026160091 0.000000E+000 True
12 -0.08800873 -0.08800873 0.000000E+000 True
13 0.16196862 0.16196862 0.000000E+000 True
14 0.91199124 0.9119913 5.960464E-008 True
15 1.97384 1.97384 0.000000E+000 True
16 3.0356889 3.0356886 2.384186E-007 True
17 4.0095997 4.0095997 0.000000E+000 True
18 4.9835114 4.983511 4.768372E-007 True
19 5.9947987 5.994799 4.768372E-007 True
20 7.006087 7.0060863 4.768372E-007 True
21 8.001913 8.001913 0.000000E+000 True
22 8.997738 8.997738 0.000000E+000 True
23 9.998984 9.998981 2.861023E-006 True
24 11.000226 11.000226 0.000000E+000 True
25 12.0001135 12.0001135 0.000000E+000 True
26 13 13 0.000000E+000 True
27 13.999999 14 9.536743E-007 True
28 15.000001 15.000001 0.000000E+000 True
29 15.999998 16 1.907349E-006 True
30 17 17.000002 1.907349E-006 True
31 18.000002 18 1.907349E-006 True
1E-06f 示例:
index expected actual difference match
0 -2.7051452E-34 -2.7051452E-34 0.000000E+000 True
1 0.00011297482 0.00011297482 0.000000E+000 True
2 0.00022594964 0.00022594964 0.000000E+000 True
3 -0.0010179491 -0.0010179491 0.000000E+000 True
4 -0.0022618477 -0.0022618477 0.000000E+000 True
5 0.0019123415 0.0019123415 0.000000E+000 True
6 0.00608653 0.00608653 0.000000E+000 True
7 -0.0052014478 -0.0052014478 0.000000E+000 True
8 -0.016489426 -0.016489424 1.862645E-009 True
9 0.009599558 0.009599558 0.000000E+000 True
10 0.035688534 0.035688538 3.725290E-009 True
11 -0.026160091 -0.026160091 0.000000E+000 True
12 -0.08800873 -0.08800873 0.000000E+000 True
13 0.16196862 0.16196862 0.000000E+000 True
14 0.91199124 0.9119913 5.960464E-008 True
15 1.97384 1.97384 0.000000E+000 True
16 3.0356889 3.0356886 2.384186E-007 True
17 4.0095997 4.0095997 0.000000E+000 True
18 4.9835114 4.983511 4.768372E-007 True
19 5.9947987 5.994799 4.768372E-007 True
20 7.006087 7.0060863 4.768372E-007 True
21 8.001913 8.001913 0.000000E+000 True
22 8.997738 8.997738 0.000000E+000 True
23 9.998984 9.998981 2.861023E-006 False
24 11.000226 11.000226 0.000000E+000 True
25 12.0001135 12.0001135 0.000000E+000 True
26 13 13 0.000000E+000 True
27 13.999999 14 9.536743E-007 True
28 15.000001 15.000001 0.000000E+000 True
29 15.999998 16 1.907349E-006 False
30 17 17.000002 1.907349E-006 False
31 18.000002 18 1.907349E-006 False
这就是我进行比较的方式:
const float delta = 1E-05f;
var expectedValue = expected[i];
var actualValue = actual[i];
var difference = Math.Abs(expectedValue - actualValue);
var failed = difference > delta;
根据文档,精度约为6到9位。
问题:
我可以比较的最低增量确实是
1E-05f
还是可能1E-06f
?
如果您确定值完全相同,则可以精确比较浮点数。但一旦你开始涉及数学,事情就会变得更加复杂,因为精度将取决于你正在执行的具体操作以及值的范围。
举个例子
(a * b) / a
。结果应该是b
,但是错误是什么呢?如果 a = float.MaxValue
和 b = float.MinValue
结果是无穷大,因此误差是无穷大。一般来说,在幅度差异较大的值之间进行运算时,精度会受到影响。
更多详细信息,请参阅我应该如何进行浮点比较?。另请参阅每个程序员应该了解的浮点运算知识
在实践中,对于单元测试,您可以使用通过测试的最低增量。这样你至少知道结果不会变得更糟。如果您需要更高的精度,您可能应该使用 double 来代替。
您应该标准化增量,只需看看(夸张的)示例:
expected : 1e-33
actual : 1e-30
delta : 9.99e-31
comment : actual is 1000 times larger than expected but stills fit your criterium
和
expected : 1e+33
actual : 1.000000000000001e+33
delta : 1e+18
comment : The difference is tiny (in 15th digit!) but delta doesn't fit your criterium
我认为你应该选择一个不同的选项,比如说
实际至少有 k 个正确数字
int digits = 6;
bool fits = Math.Abs((expected - actual) / actual) < Math.Pow(10, digits);