Created
June 11, 2019 07:00
-
-
Save somarlyonks/a154ab30ae32ce0909025c47df0fbcf3 to your computer and use it in GitHub Desktop.
123 -> 一二三 -> 壹贰叁
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const decimalism = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'] | |
| const scalar = ['', '十', '百', '千'] | |
| const modular = 10000 | |
| const modualrScalar = ['', '万', '亿', '万'] | |
| function _123To壹贰叁 (num) { | |
| if (isNaN(num)) return 'NaN' | |
| if (num === 0) return '零' | |
| if (num >= 1000000000000) return 'NaN' // 会计用兆而不是万亿,懒得转换了 | |
| const DECIMALISM = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'] | |
| const SCALAR = ['', '拾', '佰', '仟'] | |
| const UNIT = ['角', '分', '厘', '毫'] | |
| // const SCALARS = modualrScalar.map(_ => [_].concat(SCALAR.slice(-3))).flat() | |
| const yYeEsSMap = { | |
| '负': '(负数)' | |
| } | |
| decimalism.forEach((_, i) => yYeEsSMap[decimalism[i]] = DECIMALISM[i]) | |
| scalar.forEach((_, i) => yYeEsSMap[scalar[i]] = SCALAR[i]) | |
| const integer = _123To一二三(parseInt(num)) | |
| const decimal = num.toFixed(2).split('.')[1] | |
| const yuan = integer.split('').map(x => yYeEsSMap[x] || x).join('') + '圆' | |
| const fen = !parseInt(decimal[1]) ? '' : DECIMALISM[decimal[1]] + UNIT[1] | |
| const jiaofen = decimal === '00' ? '' : DECIMALISM[decimal[0]] + UNIT[0] + (fen || '整') | |
| return yuan + (jiaofen || '整') | |
| } | |
| /** | |
| * @description 另有一种写法 | |
| * Math.abs(num) | |
| * .toString().split('') | |
| * .reduce((r, c, i) => decimalism[digits[digits.length - 1 - i]] + scalars[i] + r, '') | |
| * .replace(/零(千|百|十)/g, '零') | |
| * .replace(/十零/g, '十').replace(/零+/g, '零') | |
| * .replace(/零亿/g, '亿').replace(/零万/g, '万').replace(/亿万/g, '亿') | |
| * .replace(/零+$/, '') | |
| * .replace(/^一十/, '十') | |
| * 为什么不用这个看上去要更简便的方式呢? | |
| * 原因在于这样写非常局限,而且很难实现“一百万零五千”这种转换 | |
| * | |
| * 下面的写法更灵活,更易于 transform(返回blocks的话就能进行更多操作),也因此能够更严谨 | |
| */ | |
| function _123To一二三 (num) { | |
| if (isNaN(num)) return 'NaN' | |
| if (num % 1) return 'NaN' | |
| if (num > Number.MAX_SAFE_INTEGER) return 'NaN' | |
| if (num === 0) return '零' | |
| const sign = num < 0 ? '负' : '' | |
| num = Math.abs(num) | |
| if (num === 1) return sign + '一' | |
| const blocksCount = Math.ceil(Math.log2(num) / Math.log2(modular)) | |
| const yiersan = Array.from({length: blocksCount}, (_, i) => Math.floor(num / modular ** i) % modular) | |
| .reverse() | |
| .map(block => block.toString()) | |
| .map((block, i, blocks) => | |
| (!i ? '' : block.length !== 4 || blocks[i - 1].endsWith('0') ? '零' : '') + | |
| // (block.length !== 4 && i ? '零' : '') + | |
| block.split('') | |
| .map(x => parseInt(x)) | |
| .map((x, i) => decimalism[x] + (x ? scalar[block.length - i - 1] : '')) | |
| .join('') | |
| .replace(/零+/, '零').replace(/零+$/, '') | |
| ) | |
| .map((block, i) => block + modualrScalar[blocksCount - i - 1]) | |
| .join('') | |
| .replace(/^一十/, '十') | |
| return sign + yiersan | |
| } | |
| const usecases = [ | |
| [1000, '一千'], | |
| [1001, '一千零一'], | |
| [1011, '一千零一十一'], | |
| [1101, '一千一百零一'], | |
| [11000, '一万一千'], | |
| [11001, '一万一千零一'], | |
| [101001, '十万零一千零一'] | |
| ] | |
| function test (f, u) { | |
| const e = u[1] | |
| console.log('EXPECTED:', e) | |
| const r = f(u[0]) | |
| console[r === e ? 'info' : 'error']('GOT :', r) | |
| } | |
| function tests (f, us) { | |
| us.forEach(u => test(f, u)) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment