数字转汉语输出函数

实现将数字转换为中文大写的函数,支持 10000 亿以内的数字

问题

实现一个 trans 函数,将数字转换成汉语输出,输入为不超过 10000 亿的数字。

示例:

  • trans(123456) → “十二万三千四百五十六”
  • trans(100010001) → “一亿零一万零一”

解答

实现思路

从左至右按万分位分组,每组加上对应单位(万、亿),然后对每个分组进行处理。

  • breakLen:能够分成多少个分组
  • notBreakSegment:当前已处理过的分组长度
  • zeroFlag:每个分组内 0 的个数
  • allZeroFlag:当前分组前面全为 0 的分组个数

完整代码

function trans(num) {
  if (num === 0) return '零';
  
  const numbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
  const units = ['', '十', '百', '千'];
  const bigUnits = ['', '万', '亿'];
  
  const str = num.toString();
  const len = str.length;
  
  // 计算分组数量(每 4 位一组)
  const breakLen = Math.ceil(len / 4);
  let notBreakSegment = len % 4 || 4;
  let result = '';
  let allZeroFlag = 0;
  
  for (let i = 0; i < breakLen; i++) {
    // 获取当前分组
    const start = i === 0 ? 0 : notBreakSegment + (i - 1) * 4;
    const segment = str.slice(start, start + (i === 0 ? notBreakSegment : 4));
    let segmentResult = '';
    let zeroFlag = 0;
    
    // 处理分组内的每一位
    for (let j = 0; j < segment.length; j++) {
      const digit = Number(segment[j]);
      
      if (digit === 0) {
        zeroFlag++;
      } else {
        // 如果前面有 0,需要添加"零"
        if (zeroFlag > 0 && segmentResult) {
          segmentResult += numbers[0];
        }
        segmentResult += numbers[digit] + units[segment.length - j - 1];
        zeroFlag = 0;
      }
    }
    
    // 如果当前分组不全为 0
    if (segmentResult) {
      // 如果前面有全为 0 的分组,需要添加"零"
      if (allZeroFlag > 0 && result) {
        result += numbers[0];
      }
      result += segmentResult + bigUnits[breakLen - i - 1];
      allZeroFlag = 0;
    } else {
      allZeroFlag++;
    }
  }
  
  return result;
}

测试

console.log(trans(123456));      // 十二万三千四百五十六
console.log(trans(100010001));   // 一亿零一万零一
console.log(trans(10000000000)); // 一百亿
console.log(trans(1001));        // 一千零一

关键点

  • 按万分位(每 4 位)将数字分组,分别对应个、万、亿等单位
  • 第一个分组长度可能不足 4 位,需要特殊处理
  • 使用 zeroFlag 记录分组内连续的 0,避免输出多个”零”
  • 使用 allZeroFlag 记录全为 0 的分组,处理跨分组的”零”
  • 分组全为 0 时不添加该分组的单位(如”万”、“亿”)