Skip to content

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

Open
@haizhilin2013

Description

@haizhilin2013
Collaborator

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

Activity

ghost

ghost commented on Aug 8, 2019

@ghost
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')
// => '三百二十七万四千八百二十三亿九千四百七十三万二千九百四十七亿一千零四十一万零四百一十二亿三千四百五十六万七千零八十'

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

haizhilin2013

haizhilin2013 commented on Aug 8, 2019

@haizhilin2013
CollaboratorAuthor

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

ghost

ghost commented on Aug 8, 2019

@ghost

@NicholasBaiYa

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

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

NicholasBaiYa commented on Aug 8, 2019

@NicholasBaiYa

@NicholasBaiYa

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

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

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

liuxiaole

liuxiaole commented on Aug 8, 2019

@liuxiaole

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

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

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

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

ghost

ghost commented on Aug 8, 2019

@ghost

@liuxiaole

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

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

DarthVaderrr

DarthVaderrr commented on Aug 8, 2019

@DarthVaderrr
/*
 * @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;
    }
}
liuxiaole

liuxiaole commented on Aug 9, 2019

@liuxiaole
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];
}
forever-z-133

forever-z-133 commented on Aug 12, 2019

@forever-z-133
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))
// 一亿二千三百一十二万三千一百二十三
liuxiaole

liuxiaole commented on Aug 12, 2019

@liuxiaole
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

liuxiaole commented on Aug 12, 2019

@liuxiaole

@liuxiaole

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

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

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

forever-z-133

forever-z-133 commented on Aug 13, 2019

@forever-z-133

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

感谢,代码已更新。

jiamianmao

jiamianmao commented on Aug 13, 2019

@jiamianmao

import nzh from 'nzh/cn'

nzh.encodeS(n)

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

jiamianmao

jiamianmao commented on Aug 14, 2019

@jiamianmao
    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') // 一百万

5 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    jsJavaScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @creasy2010@liuxiaole@haizhilin2013@canwdev@jiamianmao

        Issue actions

          [js] 第114天 写一个把数字转成中文的方法,例如:101转成一百零一 · Issue #1039 · haizlin/fe-interview