JS 数字转中文大写

955 阅读1分钟

uTools_1680446709015.png

数字转中文大写

覆盖范围:

  1. 最大值999999999999.999;
  2. 正整数,如1234;
  3. 负整数,如-123;
  4. 小数(保留三位),如123.456。

处理“零”:

  1. 不能出现连续的零;
  2. 数字末尾不可出现零;
  3. 位数前不可出现零,如1300000 => 一百三十万元整;

直接上代码:

/**
 * 数字转大写
 * @param {*} number
 * @returns {String} String
 */
function NumberToUppercase(number) {
  if (typeof number !== "number") {
    console.warn(`${number} is not a Number Type`);
    return number;
  }
  if (number > 999999999999.999) {
    console.warn(`${number} is out of numeric range`);
    return number;
  }
  number = number.toString();
  // 大写数字
  const upper = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
  const small = ["角", "分", "厘"];
  const digit = ["", "拾", "佰", "仟"];
  const level = ["元", "万", "亿"];
  // 是否为负数
  const isMinus = number.includes("-");
  if (isMinus) number = number.replace("-", "");
  // 是否有小数
  const hasDecimal = number.includes(".");
  // 分离整数部分和小数部分
  let integerPart, decimalPart;
  if (hasDecimal) {
    let [n, d] = Number(number).toFixed(3).split(".");
    integerPart = n.split("").map(Number);
    decimalPart = d.split("").map(Number);
  } else {
    integerPart = number.split("").map(Number);
  }
  /* 处理整数部分 */
  const integer = integerPart.reduce((res, n, i) => {
    const index = integerPart.length - i - 1;
    const idx = Math.floor(index / 4);
    const current = res[idx] ? res[idx] : (res[idx] = []);
    // upper[n] : // 转换对应的中文大写
    // n > 0 数字大于0,则添加“拾,佰,仟”到数字后面
    current.push(upper[n] + (n > 0 ? digit[index % digit.length] : ""));
    return res;
  }, []);
  const integerValue = integer.reverse().reduce((pre, val, i) => {
    const index = integer.length - i - 1;
    // 替换连续的零,仅保留一个"零"
    let cur = val.join("").replace(/零+/g, "零");
    // 去除前末尾和当前第一位为零的"零"
    if (pre[pre.length - 1] === "零" && cur.indexOf("零") === 0) {
      cur = cur.substring(1, cur.length - 1);
    }
    // 去除最后一位"零"
    if (cur.lastIndexOf("零") === cur.length - 1) {
      cur = cur.substring(-1, cur.length - 1);
    }
    return pre + cur + level[index];
  }, "");
  /* 处理小数部分 */
  let decimal;
  if (decimalPart) {
    decimal = decimalPart.reduce((res, n, i) => {
      // 转换对应的中文大写
      const value = upper[n];
      // n > 0 数字大于0,则添加“角,分,厘”到数字后面
      let current = value + (n > 0 ? small[i] : "");
      // 小数最后一位为零,则去除
      if (i === decimalPart.length - 1 && value === "零") {
        current = "";
      }
      return res + current;
    }, "");
    // 替换连续的零,仅保留一个"零"
    decimal = decimal.replace(/零+/g, "零");
  }
  // 合并数字
  const result = !hasDecimal
    ? `${integerValue}整`
    : `${integerValue}${decimal}`;
  // 为负数添加符号
  return (isMinus ? "负" : "") + result;
}

看效果: