Fe-interview: [js] 第114天 写一个把数字转成中文的方法,例如:101转成一百零一

Created on 7 Aug 2019  ·  17Comments  ·  Source: haizlin/fe-interview

第114天 写一个把数字转成中文的方法,例如:101转成一百零一

js

Most helpful comment

const digitChar = ['', ...'一二三四五六七八九']
const posChar = ['', ...'十百千万   亿']
const placeholder = '零'

function toChineseNumeralUnder万(digits) {
    let revDigits = digits.split('').reverse()
    let result = ''
    for (let pos = 0; pos < revDigits.length; pos++) {
        const digit = Number(revDigits[pos])
        if (digit)
            { result = posChar[pos] + result }
        if (digit !== 1 || pos !== 1)
            { result = digitChar[digit] + result }
        if (!digit && pos && result && !result.startsWith(placeholder))
            { result = placeholder + result }
    }
    return result
}

function toChineseNumeralUnder亿(digits) {
    let highPart = toChineseNumeralUnder万(digits.slice(-8, -4))
    if (highPart)
        { highPart += posChar[4] }
    let lowPart = toChineseNumeralUnder万(digits.slice(-4))
    return highPart + lowPart
}

function toChineseNumeral(digits) {
    let fragment = ''
    const result = []
    for (const digit of digits.split('').reverse()) {
        if (fragment.length === 8) {
            result.unshift(toChineseNumeralUnder亿(fragment))
            fragment = ''
        }
        fragment = digit + fragment
    }
    result.unshift(toChineseNumeralUnder亿(fragment))
    if (result[0].startsWith(placeholder))
        { result[0] = result[0].slice(1) }
    return result.join(posChar[8]) || placeholder
}
toChineseNumeral('0')
// => '零'
toChineseNumeral('101')
// => '一百零一'
toChineseNumeral('1000001')
// => '一百万零一'
toChineseNumeral('123456708')
// => '一亿二千三百四十五万六千七百零八'
toChineseNumeral('3274823947329471041041234567080')
// => '三百二十七万四千八百二十三亿九千四百七十三万二千九百四十七亿一千零四十一万零四百一十二亿三千四百五十六万七千零八十'

函数名很弱智,不要在意(

All 17 comments

const digitChar = ['', ...'一二三四五六七八九']
const posChar = ['', ...'十百千万   亿']
const placeholder = '零'

function toChineseNumeralUnder万(digits) {
    let revDigits = digits.split('').reverse()
    let result = ''
    for (let pos = 0; pos < revDigits.length; pos++) {
        const digit = Number(revDigits[pos])
        if (digit)
            { result = posChar[pos] + result }
        if (digit !== 1 || pos !== 1)
            { result = digitChar[digit] + result }
        if (!digit && pos && result && !result.startsWith(placeholder))
            { result = placeholder + result }
    }
    return result
}

function toChineseNumeralUnder亿(digits) {
    let highPart = toChineseNumeralUnder万(digits.slice(-8, -4))
    if (highPart)
        { highPart += posChar[4] }
    let lowPart = toChineseNumeralUnder万(digits.slice(-4))
    return highPart + lowPart
}

function toChineseNumeral(digits) {
    let fragment = ''
    const result = []
    for (const digit of digits.split('').reverse()) {
        if (fragment.length === 8) {
            result.unshift(toChineseNumeralUnder亿(fragment))
            fragment = ''
        }
        fragment = digit + fragment
    }
    result.unshift(toChineseNumeralUnder亿(fragment))
    if (result[0].startsWith(placeholder))
        { result[0] = result[0].slice(1) }
    return result.join(posChar[8]) || placeholder
}
toChineseNumeral('0')
// => '零'
toChineseNumeral('101')
// => '一百零一'
toChineseNumeral('1000001')
// => '一百万零一'
toChineseNumeral('123456708')
// => '一亿二千三百四十五万六千七百零八'
toChineseNumeral('3274823947329471041041234567080')
// => '三百二十七万四千八百二十三亿九千四百七十三万二千九百四十七亿一千零四十一万零四百一十二亿三千四百五十六万七千零八十'

函数名很弱智,不要在意(

@t532 这函数名中英文结合呢,不错不错!

@NicholasBaiYa

你好,
你的实现似乎有一些问题?
下面是我尝试的结果:

numToChinese('121')
// => '壹贰拾壹百'
numToChinese('12147238372')
// => '壹亿贰壹undefined肆千柒拾贰拾叁百捌千叁万柒百贰undefined'

@NicholasBaiYa

你好,
你的实现似乎有一些问题?
下面是我尝试的结果:

numToChinese('121')
// => '壹贰拾壹百'
numToChinese('12147238372')
// => '壹亿贰壹undefined肆千柒拾贰拾叁百捌千叁万柒百贰undefined'

唔~我在改改··位数只写到亿,下钟后在改改,感谢大佬指教

@NicholasBaiYa
你好,
你的实现似乎有一些问题?
下面是我尝试的结果:

numToChinese('121')
// => '壹贰拾壹百'
numToChinese('12147238372')
// => '壹亿贰壹undefined肆千柒拾贰拾叁百捌千叁万柒百贰undefined'

唔~我在改改··位数只写到亿,下钟后在改改,感谢大佬指教

toChineseNumeral('1000001'); // expected: 一百万零一
// actual: 一百零万零一

@liuxiaole

toChineseNumeral('1000001'); // expected: 一百万零一
// actual: 一百零万零一

试着修了一下,现在可以了。

/*
 * @param {Number} 数字 
 * @return {String} 中文数字
 * 
*/
var arg = process.argv.slice(2)[0] + '';//node命令参数

console.log(CN_Number(arg));

function CN_Number(num) {
    let str = num + '';
    let arr = [];
    let res = [];
    for (let i = str.length-1; i >=0; i -= 4) {
        arr.unshift(str.slice(i-4, i))
    }
    while (arr.length) {
        res.unshift(arr.splice(-3, 3))
    }

    let block=['亿','万',''];
    res = res.map(item =>{
       if(item.length<3) item.unshift('');
       return item.map((n,index) => {
            let res = cn_fy(n);
            res+=res?block[index]:"";
            return res;
        })
    });
    let cn_res='';
    res.forEach((a)=>{
        a.forEach(b=>{
            cn_res+=b;
        })
    })
    return  cn_res
    function cn_fy(n) {
        let unit = ['千', '百', '十'];
        let nums = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
        let res = '';
        for (let i = 0; i < n.length; ++i) {
            if (n[i] == 0) res += '零'
            else res += nums[n[i]] + (unit[i] || '')
        }
        while(res[0]==='零'){
            res=res.substring(1)
        }//去左零
        while(res[res.length-1]==='零'){
            res=res.substring(0,res.length-1)
        }//去右零
        while(res.indexOf('零零')>-1){
            res=res.replace('零','')
        }//去连续零
        return res;
    }
}
function toChineseNumeral(n) {
    let units = ['', '十', '百', '千'];
    let numbers = '零一二三四五六七八九'.split('');
    let alternateTwo = '两';

    /**
    * 按 length 把 str 切割,然后每段由 callback 来处理
    * 后用 unit 连接,同时处理段之间要不要加零
    */
    let fragmentFactory = (length, unit, callback) => {
        let fn = strNum => {
            if(strNum.length === 0) return '';
            let tail = strNum.substring(strNum.length - length, strNum.length);
            let head = strNum.substring(0, strNum.length - length);
            let headResolved = fn(head);
            if (headResolved.length > 0) {
                headResolved += unit;
                if (tail.match(/^0+[1-9]/)) {
                    headResolved += numbers[0];
                }
            }
            return headResolved + callback(tail.replace(/^0+/, ''));
        };
        return fn;
    }

    /**
    * 处理万以内的数字
    */
    let resolve4 = partition => {
        let digits = partition.split('');
        let retStr = '';
        for(let i = 0; i < digits.length; i++) {
            let d = digits[i];
            if(d === '0') continue;

            if(i >= 1 && digits[i-1] === '0') {
                retStr += numbers[0];
            }

            let unit = digits.length - i - 1;
            let isTwoThousand = d === '2' && unit === 3;
            retStr += (isTwoThousand ? alternateTwo : numbers[d]) + units[unit];
        }
        return retStr;
    };

    // 先以 8 位切,然后以 4位切
    let fragment4 = fragmentFactory(4, '万', resolve4);
    let fragment8 = fragmentFactory(8, '亿', fragment4);
    // 要 京 兆 垓 都是没有问题的
   // fragment 16 京, fragment 32 兆 一直写下去就行    

    return fragment8(String(n)) || numbers[0];
}
function returnChineseNumber(num, chineseType) {
  if (!num) return '';

  var numArr = [num].toString().split('');
  var _numConfig = '零一二三四五六七八九'.split('');
  var _unitConfig = ' 十百千'.split('');
  var _sizeConfig = ' 万亿兆'.split('');
  if (chineseType) {
    _numConfig = '零壹贰叁肆伍陆柒捌玖'.split('');
    _unitConfig = ' 拾佰仟'.split('');
    // _sizeConfig = ' 萬億兆'.split('');
  }

  var result = '';
  for (var i=0,len=numArr.length; i<len; i++) {
    var n = Number(numArr[len-i-1]);
    var cn = _numConfig[n];
    var unit = i%4 !== 0 ? _unitConfig[i%4] : '';
    var size = i%4 === 0 && i !== 0 ? _sizeConfig[i/4] : '';

    // 现在将返回 1001 => 一千零百零十一,不符合情况,则进行以下处理
    if (cn === '零') unit = '';
    if (cn === '零' && (result === '' || result.slice(0, 1) === '零')) cn = '';

    result = cn + unit + size + result;
  }

  return result;
}
console.log(returnChineseNumber(123123123))
// 一亿二千三百一十二万三千一百二十三
function returnChineseNumber(num, chineseType) {
  if (!num) return '';

  var numArr = [num].toString().split('');
  var _numConfig = '零一二三四五六七八九'.split('');
  var _unitConfig = ' 十百千'.split('');
  var _sizeConfig = ' 万亿兆'.split('');
  if (chineseType) {
    _numConfig = '零壹贰叁肆伍陆柒捌玖'.split('');
    _unitConfig = ' 拾佰仟'.split('');
    // _sizeConfig = ' 萬億兆'.split('');
  }

  var result = '';
  for (var i=0,len=numArr.length; i<len; i++) {
    var cn = _numConfig[numArr[len-i-1]];
    var unit = _unitConfig[i%4];
    var size = i%4 === 0 ? _sizeConfig[i/4] : '';
    if (unit === ' ') unit = '';
    if (size === ' ') size = '';
    if (cn === '零') unit = '';
    result = cn + unit + size + result;
  }

  return result;
}
console.log(returnChineseNumber(123123123))
// 一亿二千三百一十二万三千一百二十三

returnChineseNumber(201001);
// 预期: 二十万一千零一
// 实际: 二十零万一千零零一
returnChineseNumber(1000000);
// 预期: 一百万
//实际:一百零零万零零零零

@liuxiaole

toChineseNumeral('1000001'); // expected: 一百万零一
// actual: 一百零万零一

试着修了一下,现在可以了。

toChineseNumeral('1110');
// expected 一千一百一十
// actual 一千一百十
‘一十’ 只有在小于20才可以读作“十”或“十几”,所以干脆直接留下“一十”这种情况,或者判断“一十”是否为开头

returnChineseNumber(201001);
// 预期: 二十万一千零一
// 实际: 二十零万一千零零一
returnChineseNumber(1000000);
// 预期: 一百万
//实际:一百零零万零零零零

感谢,代码已更新。

import nzh from 'nzh/cn'

nzh.encodeS(n)

不好意思,搞定了,泡妞去了。

    function formatChineseTypeNumber(number) {
      const digitChar = [...'零一二三四五六七八九']
      const posChar = ['', ...'十百千']
      const unit = ['', '万', '亿']

      let str = ''
      let arr = number.replace(/(\d{1,4})(?=(?:\d{4})+(?!\d))/g,'$1,').split(',')

      const formatWan = (number, unit) => {
        let string = ''
        number.split('').forEach((x, i) => {
          if (x !== '0') {
            let posCharIndex = number.length - i - 1
            // 处理 `一十万` 改为 `十万`
            if (x === '1' && posCharIndex === 1) {
              string += `${posChar[posCharIndex]}`
            } else {
              string += `${digitChar[x]}${posChar[posCharIndex]}`
            }
          } else if (string.slice(-1) !== '零') {
            string += '零'
          }
        })
        while(string.slice(-1) === '零') {
          string = string.slice(0, -1)
        }
        return string && `${string}${unit}`
      }

      arr.forEach((item, index) => {
        str += formatWan(item, `${unit[arr.length - index - 1]}`)
      })
      return str
    }

    formatChineseTypeNumber('10000') // 一万
    formatChineseTypeNumber('1000') // 十万
    formatChineseTypeNumber('1000000') // 一百万
function transformNumber(number) {
        const mapping = {
            100000000: '亿',
            10000000: '千万',
            1000000: '百万',
            100000: '十万',
            10000: '万',
            1000: '千',
            100: '百',
            10: '十',
            0: '零',
            1: '一',
            2: '二',
            3: '三',
            4: '四',
            5: '五',
            6: '六',
            7: '七',
            8: '八',
            9: '九'
        }
        const keys = Object.keys(mapping).sort((a, b) => b - a);
        let retStr = '', temp = number, tempStr;
        for (let k of keys) {
            tempStr = ~~(temp / k);
            temp = temp % k;
            if (tempStr) {
                retStr += `${mapping[tempStr]}${mapping[k]}`;
            } else if (mapping[k] === '十' && tempStr === 1) {
                retStr += '一十'; // 特殊处理 10 读作 一十
            } else if (!tempStr && retStr && retStr[retStr.length - 1] !== '零') {
                retStr += '零';
            } else if (temp < 10) {
                if (temp !== 0) { // 特殊处理末尾 0
                    retStr += mapping[temp]
                }
                break; // 已到达个位数,退出循环
            }
            if (!temp) break;
        }
        console.log(retStr);
    }
    transformNumber(10101101) // 一千万零一十万零一千一百零一
/**
 * @desc
 *
 * @使用场景
 *
 * @[email protected]
 * @Date    2019/12/5
 **/

var unit = ['', '十', '百', '千'];
var segmentUnit = ['', '万', '亿','兆'];
var number = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];

function transfer(digits: number, unitIndex = 0) {
  // let segment = digits % 10000;
  // let result = digits / 10000;

  let segmentResults = [];

  let currentSegment;
  let nextVal=digits;
  do {
    currentSegment = nextVal % 10000;

    nextVal = Math.floor(nextVal / 10000);

    if (currentSegment > 0) {
      segmentResults.push((nextVal>0?"零":"")+
        transferSegment(currentSegment, segmentUnit[unitIndex++]),
      );
    }

  } while (nextVal > 0);

  return segmentResults.reverse().join('');
}

function transferSegment(segment: number, segmentUnit: string): string {
  let result = [];
  let currentValue = segment;
  let _unitIndex = 0;

  let  isLastZero= null;

  do {
    let current = currentValue % 10;
    currentValue = Math.trunc(currentValue / 10);
    let _unit =  unit[_unitIndex++];
    if (current !== 0) {
      result.push( number[current] + _unit,
      );
      isLastZero = false;
    } else {
      if(isLastZero===false){
        result.push(
          "零",
        );
      }
      isLastZero = true;
    }
  } while (currentValue > 0);



  return result.reverse().join("") + segmentUnit;
}

console.log(transfer(1000));
console.log(transfer(1001));
console.log(transfer(1011));
console.log(transfer(1111));
console.log(transfer(9999));
console.log(transfer(19999));
console.log(transfer(1000999));

function translateNumber(num) {
  var numStr = Math.round(num).toString().split('')
  if (numStr.length > 12) {
    throw '数字超过最大范围:千亿'
  }
  var digitChar = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九']
  var posChar = ['', '十', '百', '千', '万', '十', '百', '千', '亿', '十', '百', '千']
  var zeroChar = '零'
  var lastChar
  var result = numStr.map((char, index) => {
    var pos = numStr.length - 1 - index
    var res = digitChar[char]
    if (char === '0') {
      if (lastChar && lastChar !== zeroChar) { // 避免重复的零
        if (pos === 4 || pos === 8) { // 处理万和亿
          res += posChar[pos]
        } else {
          res += zeroChar
        }
      }
    } else {
      res += posChar[pos]
    }
    lastChar = digitChar[char]
    return res
  })
  result = result.filter(i => i) // 去除空白数组项
  if (result.lastIndexOf(zeroChar) === result.length - 1) { // 删除最后的零
    result.pop()
  }
  return result.join('')
}
console.log(translateNumber(5)) // 五
console.log(translateNumber(20))  // 二十
console.log(translateNumber(100)) // 一百
console.log(translateNumber(105)) // 一百零五
console.log(translateNumber(111)) // 一百一十一
console.log(translateNumber(256)) // 二百五十六
console.log(translateNumber(1024))  // 一千零二十四
console.log(translateNumber(10086)) // 一万零八十六
console.log(translateNumber(10001)) // 一万零一
console.log(translateNumber(101010))  // 一十万一千零一十
console.log(translateNumber(2050100)) // 二百零五万零一百
console.log(translateNumber(10101101))  // 一千零一十万一千一百零一
console.log(translateNumber(909090909001))  // 九千零九十亿九千零九十万九千零一
Was this page helpful?
0 / 5 - 0 ratings