0.1+0.2 != 0.3

js中数字使用64位二进制标识(IEEE 754)

  • 1个符号位
  • 11个指数位
  • 52个有效数字位
  • 最大值:2^53 - 1
  • 最小值:-2^53 + 1

小数表示

0.1

0.1二进制表示:0.0001100110011001100110011001100110011001100110011001101

  • 计算方式(尾数0011无限循环)
    • 0.1 * 2 = 0.2 取整数位0
    • 0.2 * 2 = 0.4 取整数位0
    • 0.4 * 2 = 0.8 取整数位0
    • 0.8 * 2 = 1.6 取整数位1(1.6变成0.6)
    • 0.6 * 2 = 1.2 取整数位1(1.2变成0.2)
    • 0.2 * 2 = 0.4 取整数位0
    • 0.4 * 2 = 0.8 取整数位0
    • 0.8 * 2 = 1.6 取整数位1(1.6变成0.6)
    • 0.6 * 2 = 1.2 取整数位1(1.2变成0.2)

整数表示

  • 计算方式17(倒排10001)
    • 17 / 2 = 8 ... 1 取余数1
    • 8 / 2 = 4 ... 0 取余数0
    • 4 / 2 = 2 ... 0 取余数0
    • 2 / 2 = 1 ... 0 取余数0
    • 1 / 2 = 0 ... 1 取余数1
  • 计算方式16(倒排10000)
    • 16 / 2 = 8 ... 0 取余数1
    • 8 / 2 = 4 ... 0 取余数0
    • 4 / 2 = 2 ... 0 取余数0
    • 2 / 2 = 1 ... 0 取余数0
    • 1 / 2 = 0 ... 1 取余数1

进制转换

// 二进制转10进制
parseInt(10001, 2) == 17
// 10进制转2进制
Number(0.1).toString(2) == 0.0001100110011001100110011001100110011001100110011001101

如何解决不想等问题

  • 使用字符表示相加
  • Number(0.1 + 0.2).toPrecision(12) == 0.3
    • toPrecision表示取多少位有效位,12是经验所得
  • 使用大数计算库