【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("")
}
相关推荐
思茂信息3 分钟前
CST电动车EMC仿真——电机控制器MCU滤波仿真
javascript·单片机·嵌入式硬件·cst·电磁仿真
C++业余爱好者4 分钟前
JVM优化入门指南:JVM垃圾收集器(GC)介绍
java·开发语言·jvm
Trouvaille ~10 分钟前
【Java篇】基石与蓝图::Object 类与抽象类的双重奏
java·开发语言·javase·抽象类·类与对象·基础入门·object类
鲸落落丶11 分钟前
Vue Router路由
前端·javascript·vue.js
小光学长13 分钟前
基于ssm的美妆产品推荐系统rah0h134(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
java·数据库·spring
阿呜的边城15 分钟前
终于还是吃上了react-i18next的细糠
前端·前端框架
Light6022 分钟前
破局“数据孤岛”:构建业务、财务、指标三位一体的智能数据模型
java·大数据·开发语言
中文很快乐23 分钟前
从零到一:用 SpringBoot 打造 RESTful API 实战指南
java·spring boot·后端·restful
米方23 分钟前
ElementPlus 穿梭框支持批量穿梭
前端·javascript·vue.js
InkHeart24 分钟前
uni-app开发路上的坑
前端·vue.js