Chr*_*Bag 2 javascript floating-point binary equality
为我的 Javascript 程序编写一些测试用例来处理二进制文件,现在我只是使用 stringify 来检查值和预期值是否相等:
JSON.stringify(val) === JSON.stringify(expected)
Run Code Online (Sandbox Code Playgroud)
这工作正常,除非我有浮点值。这是发生的事情:
Given Value: [10,20,30,32.400001525878906,{"test":3,"asdf":23}]
Expected Value: [10,20,30,32.4,{"test":3,"asdf":23}]
Test Failed!
Run Code Online (Sandbox Code Playgroud)
所以我想我不能再使用 stringify 来检查我的两个对象/数组是否相等。检查两个潜在的深度嵌套对象/数组是否相等同时还要考虑浮点值的好方法是什么?也就是说,如果两个浮点值 99.99% 相同或其他什么,则应认为它们相等。
您需要按顺序测试数组中的每个元素,并且需要对对象递归地进行测试。这通常被称为深度比较或深度相等。您应该能够使用检查比较数类型的递归函数来执行此操作。
比较浮点值时,您需要使用容差。您可以通过取两个数字相减的绝对值,然后将其与您选择的固定容差值或称为 epsilon 的小数进行比较来实现。
在 JavaScript 中,机器 epsilon 可用作Number.EPSILON,并定义为 1 与大于 1 的最小数字之间的差,可以表示为 a Number。大多数语言中都有类似的常量,通常用于基于容差的比较。
基于容差的比较将浮点比较从简单的相等转换为减法和比较。如果你通常写
if (a === b) { ... }
Run Code Online (Sandbox Code Playgroud)
你会写使用绝对值和 atolerance来消除浮点怪异:
var tolerance = Number.EPSILON;
if (Math.abs(a - b) < tolerance) { ... }
Run Code Online (Sandbox Code Playgroud)
如果之间的差别a和b小于tolerance,你把他们当作平等的。
有关更细微(但可能对您的案例来说太过分了)的方法,请参阅浮点指南中关于比较的部分。那里提供的实现是用 Java 编写的,但很可能无需太多努力即可移植到 JavaScript。