JS - 价格千分位分割

# 价格千分位分割

使用正则表达式 /\B(?=(\d{3})+(?!\d))/g

\B: 匹配一个非单词边界

x(?=y): 先行断言, 当 'x' 后面跟着'y'. 例如 /Jace(?=Sparat)/ 匹配到 'Sparat'.

(?!pattern) 负向预查. 在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始

function formatterPrice(price) {
  return String(price).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

// Test
console.log(formatterPrice(12321134324324234))
// '12,321,134,324,324,234'
1
2
3
4
5
6
7

但是这种不能输入不能有小数点, 所以改造下

function formatterPrice(price) {
  const part = String(price).split('.')
  part[0] = part[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',')

  return part.join('.')
}

// Test
console.log(formatterPrice(12321.01))
// 12,321.01
console.log(formatterPrice(5683321.021))
// 5,683,321.021
1
2
3
4
5
6
7
8
9
10
11
12

但是这种不能处理超过最大安全数([-(2 ^ 53 - 1), (2 ^ 53 - 1)]), 例如, formatterPrice(12321134324324234.08), 结果始终是 12,321,134,324,324,234, 究其根源, 具体涉及到底层的存储,运算机制[1]

# 0.1 + 0.2 = 0.3 精度问题解决

以下解决方案只能处理在最大安全数范围内的数

// 1. 考虑浮点数偏差小, 这种也会有特殊情况下不能处理, 如 210000 * 10000  * 1000 * 8.2 
const formatFloat = (n) => parseInt(n.toFixed(12))
formatFloat(0.1 + 0.2) // 0.3

// 2. 浮点化整, 这种也不能处理最大安全数
const getDecimal = n => String(n).replace(/^(\+|\-)?\d+\.(\d+)/g, '$2')
// getDecimal(3.1415926535) => '1415926535'
const formatFloat2 = (n1, n2) => {
  let delta, decimalN1, decimalN2
  try {
    // decimalN1 = String(n1).split('.')[1].length
    decimalN1 = getDecimal(n1).length
  } catch(e) { decimalN1 = 0 }
  try {
    // decimalN2 = String(n2).split('.')[1].length
    decimalN2 = getDecimal(n2).length
  } catch(e) { decimalN2 = 0 }

  delta = Math.pow(10, Math.max(decimalN1, decimalN2))

  return (n1 * delta + n2 * delta) / delta
}

// 3. 借助第三方库, 模拟实际运算的过程, 目前也有比较成熟的库
// - bignumber.js: https://github.com/MikeMcl/bignumber.js/blob/master/bignumber.js
// - big.js: https://github.com/MikeMcl/big.js/blob/master/big.js
// - decimal.js: https://github.com/MikeMcl/decimal.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 参考链接


  1. JavaScript 浮点数之迷: 0.1 + 0.2 为什么不等于 0.3? (opens new window) ↩︎