Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

将数字格式化成金额的形式并四舍五入保留 x 位小数 #10

Open
yeojongki opened this issue Jun 22, 2019 · 1 comment
Open

Comments

@yeojongki
Copy link
Owner

yeojongki commented Jun 22, 2019

将数字格式化成金额的形式并四舍五入保留 x 位小数

一. 保留 x 位小数

如: 1234.781 转化为 1,234.78
tofix 存在的问题: JavaScript 浮点数陷阱及解法

另外的办法:Math.round(X * 保留的位数) / 保留的位数

/**
 * 将数字四舍五入保留 x 位小数
 * @param {Number|String} num 传入的数字
 * @param {Number} len 要保留的小数位 如 2 位小数
 * @return {String} result
 * @example handleTail(100.234, 2) -> 100.23
 */
const handleTail = (num, len) => {
  // 扩大相应倍数
  let scale = Math.pow(10, len)
  // 再缩小到原来的倍数
  return Math.round(+num * scale) / scale
}

二. 将数字格式化成金额的形式

/**
 * 将数字格式化成金额的形式
 * @param {Number|String} num 传入的数字(必须是整数!!)
 * @return {String} result
 * @example thoudsandNum(123456) -> 123,456
 */
const thoudsandNum = num => {
  // 判断是否是正数
  let isPosive = true
  if (+num < 0) isPosive = false
  num = Math.abs(num)
  let prefix = isPosive ? '' : '-'
  // 正则相关 https://juejin.im/post/5965943ff265da6c30653879#heading-10
  let ret = ('' + num).replace(/(?!^)(?=(\d{3})+$)/g, ',')
  return prefix + ret
}

三. 分割小数整数部分最终合并

const parseMoney = (num, len = 2) => {
  // 判断输入合法数字
  if (!/^-?\d+$|^(-?\d)+(\.)?\d+$/.test('' + num) || !/^\d+$/.test('' + len)) {
    throw new Error('invalid param `num` or `len`')
  }
  // 取出整数和小数部分
  let [head, tail] = handleTail(num, len).split('.')
  // 处理整数千分位
  head = thoudsandNum(head)
  return `${head}.${tail}`
}

另外还需要处理一些问题:没有小数,或者小数尾数不足的时候补 0

完整代码

/**
 * 将数字格式化成金额的形式并四舍五入保留 x 位小数
 * @param {Number|String} num 传入的数字
 * @param {Number} len 要保留的小数位 (只能是正整数) 如 2 位小数
 * @return {String} result
 * @example parseMoney(-1234564.789) -> -1,234,564.79
 */
const parseMoney = (num, len = 2) => {
  // 判断输入合法数字
  if (!/^-?\d+$|^(-?\d)+(\.)?\d+$/.test('' + num) || !/^\d+$/.test('' + len)) {
    throw new Error('invalid param `num` or `len`')
  }
  // 扩大相应倍数
  let scale = Math.pow(10, len)
  // 再缩小到原来的倍数
  let scaleBack = Math.round(+num * scale) / scale
  // 取出整数和小数部分
  let [head, tail] = ('' + scaleBack).split('.')
  // 补零
  function fillZero(num) {
    let ret = num ? num : ''
    for (let i = 1; i < len; i++) {
      ret += '0'
    }
    return ret
  }
  // 小数尾数补0
  tail = fillZero(tail)
  // 处理整数千分位
  // 处理正负数
  const isPosive = (num == (num = Math.abs(num)))
  head = ('' + Math.abs(head)).replace(/(?!^)(?=(\d{3})+$)/g, ',')
  // 正负号
  let prefix = isPosive ? '' : '-'
  return `${prefix}${head}.${tail}`
}
parseMoney(1234564.789) // 1,234,564.79
parseMoney(1234564.781) // 1,234,564.78
parseMoney(1234564) // 1,234,564.00
parseMoney(-1234564) // -1,234,564.00
parseMoney(-1234564.6) // -1,234,564.60
parseMoney(-1234564.789) // -1,234,564.79
parseMoney(-1234564.6, 4) // -1,234,564.6000
@yeojongki
Copy link
Owner Author

补充一种快捷格式化方法:

const num = 123456789
// 格式化千分位输出
num.toLocaleString() // "123,456,789"

// 格式化为千分位带$符号输出
num.toLocaleString("en-US",{style:"currency",currency:"USD"}) // "$123,456,789.00"

// 格式化为带¥符号输出
num.toLocaleString("zh-Hans-CN",{style:"currency",currency:"CNY"}) // "¥123,456,789.00"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant