Skip to content

数字转中文

作者:Yuan Tang
更新于:5 个月前
字数统计:891 字
阅读时长:3 分钟

思路

通过一个函数实现数字转中文,通过以下的思路实现:

  1. 把数字转为字符串,从后面开始4位的分割成数组,再过滤空项
  2. 循环数组,得到每项最多4个数字的数据
  3. 循环该数据得到每一个数字,设置一个映射表数组,把得到的数字转换数字类型作为索引获取相应的映射对象
  4. 设置一个单位数组映射表,通过计算索引获取对应的单位

初步实现

千位数以内

js
function toChineseNumber(num) {
  // 数字裁剪
  const numStr = num
    .toString()
    .replace(/(?=(\d{4})+$)/g, ',')
    .split(',')
    .filter(Boolean)

  // 单位映射表
  const chars = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
  const units = ['', '十', '百', '千']

  // 四个数字各自添加单位
  function _transform(n) {
    let res = ''
    for (let i = 0; i < n.length; i++) {
      const c = chars[+n[i]]
      const u = units[n.length - 1 - i]
      res += c + u
    }
  }

  // 裁剪后的字符串循环遍历每一项的四个数字
  for (let i = 0; i < numStr.length; i++) {
    const part = numStr[i]
    const c = _transform(part)
  }
}

console.log(toChineseNumber(5678)) // 五千六百七十八

优化

咋一看已经实现了,但是经过测试后还是有一定的小问题,比如:

  • 如果输入数字 1203,它会返回一千两百零十三,但是十位数为零一般不需要带单位,需要做判断
  • 如果输入数字 1003,它会返回一千零百零十三,连续的两个零应该只需要返回一个零,需要做判断
  • 如果输入数字 1200,经过上面的处理后它会返回一千两百零,末尾的零应该省略掉,需要做判断
  • 如果输入数字 0000,经过上面的处理后它会返回空,应该返回一个零,需要做判断
js
function toChineseNumber(num) {
  // ...

  function handleZero(str) {
    return str.replace(/{2,}/g, '零').replace(/+$/g, '')
  }

  // 四个数字各自添加单位
  function _transform(n) {
    // 如果 0000 ,返回零
    if (n === '0000')
      return chars[0]

    let res = ''
    for (let i = 0; i < n.length; i++) {
      const c = chars[+n[i]]
      const u = units[n.length - 1 - i]
      // 如果是零,不设置单位
      if (c === chars[0])
        u = ''

      res += c + u
    }
    // 去除重复零以及末尾的零
    res = handleZero(res)
    return res
  }

  // ...
}

完善实现

四位数以内已经实现了,现在要把万和亿的单位添加上去,完善功能,代码如下:

js
function toChineseNumber(num) {
  // ...

  // 裁剪后的字符串循环遍历每一项的四个数字
  const bigUnits = ['', '万', '亿']
  let result = ''
  for (let i = 0; i < numStr.length; i++) {
    const part = numStr[i]
    const c = _transform(part)
    const u = bigUnits[numStr.length - 1 - i]
    // 如果是零,不设置单位
    if (c === chars[0])
      u = ''

    result += c + u
  }
  result = handleZero(result)
  return result
}

完整代码

js
function toChineseNumber(num) {
  // 数字裁剪
  const numStr = num
    .toString()
    .replace(/(?=(\d{4})+$)/g, ',')
    .split(',')
    .filter(Boolean)

  // 单位映射表
  const chars = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']
  const units = ['', '十', '百', '千']

  function handleZero(str) {
    return str.replace(/{2,}/g, '零').replace(/+$/g, '')
  }

  // 四个数字各自添加单位
  function _transform(n) {
    // 如果 0000 ,返回零
    if (n === '0000')
      return chars[0]

    let res = ''
    for (let i = 0; i < n.length; i++) {
      const c = chars[+n[i]]
      const u = units[n.length - 1 - i]
      // 如果是零,不设置单位
      if (c === chars[0])
        u = ''

      res += c + u
    }
    // 去除重复零以及末尾的零
    res = handleZero(res)
    return res
  }

  // 裁剪后的字符串循环遍历每一项的四个数字
  const bigUnits = ['', '万', '亿']
  let result = ''
  for (let i = 0; i < numStr.length; i++) {
    const part = numStr[i]
    const c = _transform(part)
    const u = bigUnits[numStr.length - 1 - i]
    // 如果是零,不设置单位
    if (c === chars[0])
      u = ''

    result += c + u
  }
  result = handleZero(result)
  return result
}

Contributors

Yuan Tang