翻译平台有一个相似度检测的功能,其中有一个计算两个字符串相似度的函数结果发现两个完全一模一样的字符串返回的相似度竟然为image.png ,根据 余弦相似度算法[1] 得到 ,小于用户传递的最小相似度阈值1,因此归到了低相似度的文本中了。
为什么会这样:

因为计算机执行的是二进制,并且js中数字都是浮点数表示的,并且规定了是 IEEE754的标准的双精度浮点数。

IEEE 754 规定了两种基本浮点格式:单精度和双精度。

单精度格式:具有24 位有效数字精度(包含符号),并总共占用32 位。

双精度格式:具有53 位有效数字精度(包含符号),并总共占用64 位。

再次深入一下:

我们使用 0.1 + 0.2进行推算

0.1转换为二进制 => 0.0001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1001 1100 ...

0.2转换为二进制 => 0.0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 0011 ...

相加 => 0.0100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100 1100

按照IEEE 754标准保留 52位,按权相加法, 0舍1入 来取值 => sum ≈ 0.30000000000000004

解决方案:

  1. tofixed

优点:简单粗暴

缺点:不会四舍五入

如下图:
image.png

  1. 小数->整数->小数 (即十进制的先左移然后右移)
  2. 可以使用第三方库

Math.js 用于 JavaScript 和 Node.js 的扩展数学库。 它具有支持符号计算的灵活表达式解析器,大量内置函数和常量,并提供了集成的解决方案来处理不同的数据类型,例如数字,大数,复数,分数,单位和矩阵。强大且易于使用。

decimal.js JavaScript 的任意精度的十进制类型。

big.js 一个小型,快速,易于使用的库,用于任意精度的十进制算术运算。

从周下载量来说无脑选big.js, 用法也非常简单.

参考资料 :

  1. https://www.cnblogs.com/airne...

2.https://www.withyou.ink/bignu...


骆佳俊
1 声望0 粉丝