【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("")
}
相关推荐
CV工程师丁Sir2 小时前
ArkWeb 手记 04|DevTools 调试与缓存清理
java·spring·缓存·harmonyos
Sarvartha8 小时前
final 关键字
java·开发语言
2601_952047798 小时前
单一策略深度教程:用轻易云把集成任务的报错实时推送到钉钉机器人
java·机器人·钉钉
程序员Sunday9 小时前
JavaScript 事件循环面试题,宏任务与微任务怎么执行|Sunday面试指南
开发语言·javascript·面试·校招·事件循环·程序员sunday
Setsuna_F_Seiei9 小时前
前端转型 Agent 开发 06 之 Agent Memory 记忆系统(让 Agent 更智能,更懂你)
前端·agent·ai编程
数据狐(Datafox)9 小时前
淘宝图片搜索 API 落地实战:基于以图搜货搭建跨境电商选品系统
java·大数据·微服务
zhangzeyuaaa10 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
默_笙10 小时前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
优选资讯10 小时前
标签打印软件怎么对接 Excel 数据
前端·excel