【JS】数字转中文读写方式

前言

封装一个函数,实现将一段阿拉伯数字转为中文读法,如:12345678 => "一千两百三十四万五千六百七十八"。需注意二和两的使用。

思路

根据中文读法,每四位都以千为最高单位读写,每四位后添加单位,所以需要对阿拉伯数字先进行四位分割,然后遍历修改为对应四位读法,然后根据分割后元素数量拼接对应单位。

实现

1. 初步实现

将num四位分割,封装_transform用于处理分割后的每一组四位数字。

javascript 复制代码
function toChineseNumber(num) {
  const strs = num
    .toString()
    .replace(/(?=(\d{4})+$)/g, ",")
    .split(",")
    .filter(Boolean) // 过滤掉空字符串

  const chars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
  const units = ["", "十", "百", "千"]
  
  function _transform(numStr) {
    let result = ""
    for (let i = 0; i < numStr.length; i++) {
      const digit = numStr[i]
      const c = chars[digit]
      const u = units[numStr.length - 1 - i]
      result += c + u
    }
    console.log(result)
  }
  _transform("1234")
}

toChineseNumber(1234567)

考虑0的情况

但如果传入数字包含0,则会出现问题。1204会返回"一千二百零十四",继续优化,为零则不拼接单位

javascript 复制代码
function _transform(numStr) {
   let result = ""
   for (let i = 0; i < numStr.length; i++) {
     const digit = numStr[i]
     const c = chars[digit]
     const u = units[numStr.length - 1 - i]
     if(digit === 0){
		result += c
	 } else {
	 	result += c + u
	 }
   }
   console.log(result)
 }

还需要考虑多个连续的零,继续优化,如果当前result末位为零则不再拼接

javascript 复制代码
function _transform(numStr) {
  let result = ""
  for (let i = 0; i < numStr.length; i++) {
    const digit = Number(numStr[i])
    const c = chars[digit]
    const u = units[numStr.length - 1 - i]
    if (digit === 0) {
      // 如果上位为零则不拼接
      if (result[result.length - 1] !== chars[0]) { 
        result += c
      }
    } else {
      result += c + u
    }
  }
  console.log(result)
}

遍历完成后末位不能为零

javascript 复制代码
function _transform(numStr) {
  let result = ""
  
  for (let i = 0; i < numStr.length; i++) {
    const digit = Number(numStr[i])
    const c = chars[digit]
    const u = units[numStr.length - 1 - i]
    if (digit === 0) {
      if (result[result.length - 1] !== chars[0]) {
        result += c
      }
    } else {
      result += c + u
    }
  }
  
  // 遍历完成后删除末位0
  if (result[result.length - 1] === chars[0]) {
    result = result.slice(0, -1)
  }
  
  return result
}

至此,_transform函数已完善。

3. 整体实现

javascript 复制代码
function toChineseNumber(num) {
  const strs = num
    .toString()
    .replace(/(?=(\d{4})+$)/g, ",")
    .split(",")
    .filter(Boolean) // 过滤掉空字符串

  const chars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
  const units = ["", "十", "百", "千"]
  const bigUnits = ["", "万", "亿"]
  
  function _transform(numStr) {
    let result = ""
    for (let i = 0; i < numStr.length; i++) {
      const digit = Number(numStr[i])
      const c = chars[digit]
      const u = units[numStr.length - 1 - i]
      if (digit === 0) {
        if (result[result.length - 1] !== chars[0]) {
          result += c
        }
      } else {
        result += c + u
      }
    }
    if (result[result.length - 1] === chars[0]) {
      result = result.slice(0, -1)
    }
    return result
  }

  let result = ""
  for (let i = 0; i < strs.length; i++) {
    const part = strs[i]
    const c = _transform(part)
    const u = bigUnits[strs.length - 1 - i]
    result += c + u
  }
  console.log(result)

  return result
}

至此还会有问题,当前_transform可以正确处理0,但是如果四位分割后某一组恰好全为零,则有问题,如1200003456打印却为十二亿万三千四百五十六,所以需要判断如果中间某一组全为零则不拼接单位。

javascript 复制代码
function toChineseNumber(num) {
  const strs = num
    .toString()
    .replace(/(?=(\d{4})+$)/g, ",")
    .split(",")
    .filter(Boolean) // 过滤掉空字符串

  const chars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
  const units = ["", "十", "百", "千"]
  const bigUnits = ["", "万", "亿"]
  
  function _transform(numStr) {
    let result = ""
    for (let i = 0; i < numStr.length; i++) {
      const digit = Number(numStr[i])
      const c = chars[digit]
      const u = units[numStr.length - 1 - i]
      if (digit === 0) {
        if (result[result.length - 1] !== chars[0]) {
          result += c
        }
      } else {
        result += c + u
      }
    }
    if (result[result.length - 1] === chars[0]) {
      result = result.slice(0, -1)
    }
    return result
  }

  let result = ""
  for (let i = 0; i < strs.length; i++) {
    const part = strs[i]
    const c = _transform(part)
    const u = c ? bigUnits[strs.length - 1 - i] : ""
    result += c + u
  }
  console.log(result)

  return result
}

一十作为开头需要处理成

javascript 复制代码
function toChineseNumber(num) {
  const strs = num
    .toString()
    .replace(/(?=(\d{4})+$)/g, ",")
    .split(",")
    .filter(Boolean) // 过滤掉空字符串

  const chars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
  const units = ["", "十", "百", "千"]
  const bigUnits = ["", "万", "亿"]
  function _transform(numStr) {
    let result = ""
    for (let i = 0; i < numStr.length; i++) {
      const digit = Number(numStr[i])
      const c = chars[digit]
      const u = units[numStr.length - 1 - i]
      if (digit === 0) {
        if (result[result.length - 1] !== chars[0]) {
          result += c
        }
      } else {
        result += c + u
      }
    }

    if (result[result.length - 1] === chars[0]) {
      result = result.slice(0, -1)
    }
    return result
  }

  let result = ""
  for (let i = 0; i < strs.length; i++) {
    const part = strs[i]
    const c = _transform(part)
    const u = c ? bigUnits[strs.length - 1 - i] : ""
    result += c + u
  }

  // 处理 "一十" 的情况,去掉开头的 "一"
  if (result.startsWith("一十")) {
    result = result.replace("一十", "十")
  }
  console.log(result)

  return result
}

toChineseNumber(1000342342)

如果需要将千位的变成

javascript 复制代码
function _transform(numStr) {
  let result = ""
  for (let i = 0; i < numStr.length; i++) {
    const digit = Number(numStr[i])
    let c = chars[digit]
    const u = units[numStr.length - 1 - i]
    if (digit === 0) {
      if (result[result.length - 1] !== chars[0]) {
        result += c
      }
    } else {
      // 处理2的情况,在千位时变为"两"
      if (digit === 2 && u === "千") {
        c = "两"
      }
      result += c + u
    }
  }

  if (result[result.length - 1] === chars[0]) {
    result = result.slice(0, -1)
  }
  return result
}

实现代码

javascript 复制代码
function toChineseNumber(num) {
  const strs = num
    .toString()
    .replace(/(?=(\d{4})+$)/g, ",")
    .split(",")
    .filter(Boolean) // 过滤掉空字符串

  const chars = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"]
  const units = ["", "十", "百", "千"]
  const bigUnits = ["", "万", "亿"]
function _transform(numStr) {
  let result = ""
  for (let i = 0; i < numStr.length; i++) {
    const digit = Number(numStr[i])
    let c = chars[digit]
    const u = units[numStr.length - 1 - i]
    if (digit === 0) {
      if (result[result.length - 1] !== chars[0]) {
        result += c
      }
    } else {
      // 处理2的情况,在非个位时变为"两"
      if (digit === 2 && u === "千") {
        c = "两"
      }
      result += c + u
    }
  }

  if (result[result.length - 1] === chars[0]) {
    result = result.slice(0, -1)
  }
  return result
}

  let result = ""
  for (let i = 0; i < strs.length; i++) {
    const part = strs[i]
    const c = _transform(part)
    const u = c ? bigUnits[strs.length - 1 - i] : ""
    result += c + u
  }

  // 处理 "一十" 的情况,去掉开头的 "一"
  if (result.startsWith("一十")) {
    result = result.replace("一十", "十")
  }

  return result
}

拓展

如果需要匹配为壹贰叁这种写法,只需要映射即可:

javascript 复制代码
function toChineseBigNumber(num) {
  const str = toChineseNumber(num)
  const map = {
    零: "零",
    一: "壹",
    二: "贰",
    两: "贰",
    三: "叁",
    四: "肆",
    五: "伍",
    六: "陆",
    七: "柒",
    八: "捌",
    九: "玖",
    十: "拾",
    百: "佰",
    千: "仟",
    万: "萬",
    亿: "億",
  }

  return str
    .split("")
    .map((s) => map[s])
    .join("")
}
相关推荐
轻口味6 分钟前
命名空间与模块化概述
开发语言·前端·javascript
前端小小王41 分钟前
React Hooks
前端·javascript·react.js
苹果醋31 小时前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
迷途小码农零零发1 小时前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
娃哈哈哈哈呀1 小时前
vue中的css深度选择器v-deep 配合!important
前端·css·vue.js
菠萝蚊鸭1 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0072 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程