浮点测试断言-为什么这些“相同”数组失败


Floating point test assertion - why do these "identical" arrays fail?

我在PHPUnit中使用assertSame()来比较数据库结果与期望值。结果为浮点数。

PHPUnit返回此消息(但我无法发现任何差异):

Failed asserting that Array (
    '1_1' => 11.111111111111
    '1_2' => 33.333333333333
    '1_3' => 55.555555555556
    '1_4' => 0.0
    '1_5' => null
    '1_total' => 100.0
) is identical to Array (
    '1_1' => 11.111111111111
    '1_2' => 33.333333333333
    '1_3' => 55.555555555556
    '1_4' => 0.0
    '1_5' => null
    '1_total' => 100.0
)

为什么会失败,比较浮点值数组的正确方法是什么?

assertEquals在这种情况下有一个$floating_delta参数:

$this->assertEquals($expected_array, $actual_array, '', 0.00001);

PHPUnit)文档

问题几乎肯定是浮点精度。在print_r中,只显示了这么多数字。如果显示所有有效位,情况可能如下所示:

Failed asserting that Array (
    '1_1' => 11.1111111111110347
    '1_2' => 33.3333333333331678
    '1_3' => 55.5555555555562773
    '1_4' => 0.0
    '1_5' => null
    '1_total' => 100.0
) is identical to Array (
    '1_1' => 11.1111111111110346
    '1_2' => 33.3333333333331679
    '1_3' => 55.5555555555562771
    '1_4' => 0.0
    '1_5' => null
    '1_total' => 100.0
)

每个浮点数比较,特别是equal,必须考虑缺少无限精度。

if ($var == 0.005)     /* just plain wrong! */
if (abs ($var, 0.005) < 0.001)    /*  more correct  */
if (abs ($var, 0.005) < 0.0001)    /* maybe more correct, depending on application */
if (abs ($var, 0.005) < 0.0000001)    /* possibly more appropriate */

除非有人有更好的建议,否则我将假设这是一个浮点精度错误,并遵循PHP手册的建议:不要直接比较浮点数是否相等

所以我自己的解决方案是在比较之前将数组值四舍五入