js如何实现阿拉伯数字转中文大写数字
前言
最近有個需求,需要把阿拉伯數字轉成中文大寫數字,比如:100 轉換成壹佰元。話不多說,擼起袖子就是干,做野!
規則
首先我們看看百度百科大寫數字,對大寫規則的描述:
中文大寫數字到"元"為止的,在"元"之后,應寫"整"(或"正")字,在"角"之后,可以不寫"整"(或"正")字。大寫數字有"分"的,“分"后面不寫"整”(或"正")字。
阿拉伯數字中有"0"時,舉例如下:
數字中間有"0"時,中文大寫要寫"零"字,如 1409.50,應寫成壹仟肆佰零玖元伍角。
數字中間連續有幾個"0"時,中文大寫中間可以只寫一個"零"字,如 6007.14,應寫成陸仟零柒元壹角肆分。
數字萬位和元位是"0",或者數字中間連續有幾個"0",萬位、元位也是"0",但千位、角位不是"0"時,中文大寫可以只寫一個零字,也可以不寫"零"字。如 1680.32,應寫成壹仟陸佰捌拾元零叁角貳分,或者寫成壹仟陸佰捌拾元叁角貳分,又如 107000.53,應寫成壹拾萬柒仟元零伍角叁分,或者寫成壹拾萬零柒仟元伍角叁分。
數字角位是"0",而分位不是"0"時,中文大寫"元"后面應寫"零"字。如 16409.02,應寫成壹萬陸仟肆佰零玖元零貳分;又如 325.04,應寫成叁佰貳拾伍元零肆分。
思路
咋一看有點懵,這么多規則。其實稍微拆分下,問題不大。主要按以下幾個步驟來實現:
數字分成整數跟小數兩個部分:
根據規則做相應的兼容,跟人生一樣充滿兼容。
實現
定個小目標,轉換一個億
我們需要將數字拆成整數部分與小數部分兩部分,然后再把這兩部分再拆成一個個數字。
function number2text(number) {const numbers = String(Number(number).toFixed(2)).split(".");const integer = numbers[0].split("");const decimal = Number(numbers[1]) === 0 ? [] : numbers[1].split("");console.log({ integer, decimal }); }number2text(100000000);于是我們得到這樣兩個數組:
 
配置
大寫數字的 0-9;
計數單位,第一位不顯示,所以空出來;
級數,后面是兆、京、垓等,基本不用可以忽視;
四位分級
通過四位分級獲取級數列表:將整數部分反轉,從個位開始處理,獲取計數單位并組裝,然后塞進個級,如果個級塞滿 4 個計數單位,則塞進萬級,以此類推。
const levels = integer.reverse().reduce((pre, item, idx) => {let level = pre[0] && pre[0].length < 4 ? pre[0] : [];// 獲取計數單位并組裝let value =item === "0" ? conf.num[item] : conf.num[item] + conf.unit[idx % 4];level.unshift(value);if (level.length === 1) {pre.unshift(level);} else {pre[0] = level;}return pre; }, []);于是我們得到這樣一個數組:
 
整數組裝
遍歷級數列表,同時拼接上級數名。
const _integer = levels.reduce((pre, item, idx) => {// 獲取級數let _level = conf.level[levels.length - idx - 1];let _item = item.join("");return pre + _item + _level; }, "");console.log({ _integer });此時我們得到這樣一個結果:
 
這顯然不是我們想要的結果,多了很多零,同時零萬也是多余,做下兼容:
const _integer = levels.reduce((pre, item, idx) => {let _level = conf.level[levels.length - idx - 1];// 連續多個零字的部分設置為單個零字let _item = item.join("").replace(/(零)\1+/g, "$1");// 如果這一級只有一個零字,則去掉這級if (_item === "零") {_item = "";_level = "";// 否則如果末尾為零字,則去掉這個零字} else if (_item[_item.length - 1] === "零") {_item = _item.slice(0, _item.length - 1);}return pre + _item + _level; }, "");console.log({ _integer });此時的結果基本 OK 了:
但是根據第 1 條規則,還少了個整元。問題不大,我們處理完小數部分,再做兼容。
小數部分
小數部分簡單遍歷即可。
let _decimal = decimal.map((item, idx) => {const unit = ["分", "角"];const _unit = item !== "0" ? unit[unit.length - idx - 1] : "";return `${conf.num[item]}${_unit}`;}).join("");輸出
最后把之前漏掉的整元字補上,到此小目標一個億實現了。
// 如果是整數,則補個整字 return `${_integer}元` + (_decimal || "整");測試
代碼寫完只能說完成一半,只有測試通過才能說,這個功能實現了,我們按照規則的示例測試下:
number2text(100000000); //壹億元整 number2text(1409.5); //壹仟肆佰零玖元伍角零 number2text(6007.14); //陸仟零柒元壹角肆分 number2text(1680.32); //壹仟陸佰捌拾元叁角貳分 number2text(107000.53); //壹拾萬柒仟元伍角叁分 number2text(16409.02); //壹萬陸仟肆佰零玖元零貳分 number2text(325.04); //叁佰貳拾伍元零肆分1680.32 可以寫成壹仟陸佰捌拾元零叁角貳分,或者寫成壹仟陸佰捌拾元叁角貳分,測試通過,收工!
完整代碼
/*** @description 數字轉中文數碼** @param {Number|String} num 數字[正整數]* @param {String} type 文本類型,lower|upper,默認upper** @example number2text(100000000) => "壹億元整"*/ export const number2text = (number, type = "upper") => {// 配置const confs = {lower: {num: ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"],unit: ["", "十", "百", "千", "萬"],level: ["", "萬", "億"]},upper: {num: ["零", "壹", "貳", "叁", "肆", "伍", "陸", "柒", "捌", "玖"],unit: ["", "拾", "佰", "仟"],level: ["", "萬", "億"]},decimal: {unit: ["分", "角"]},maxNumber: 999999999999.99};// 過濾不合法參數if (Number(number) > confs.maxNumber) {console.error(`The maxNumber is ${confs.maxNumber}. ${number} is bigger than it!`);return false;}const conf = confs[type];const numbers = String(Number(number).toFixed(2)).split(".");const integer = numbers[0].split("");const decimal = Number(numbers[1]) === 0 ? [] : numbers[1].split("");// 四位分級const levels = integer.reverse().reduce((pre, item, idx) => {let level = pre[0] && pre[0].length < 4 ? pre[0] : [];let value =item === "0" ? conf.num[item] : conf.num[item] + conf.unit[idx % 4];level.unshift(value);if (level.length === 1) {pre.unshift(level);} else {pre[0] = level;}return pre;}, []);// 整數部分const _integer = levels.reduce((pre, item, idx) => {let _level = conf.level[levels.length - idx - 1];let _item = item.join("").replace(/(零)\1+/g, "$1"); // 連續多個零字的部分設置為單個零字// 如果這一級只有一個零字,則去掉這級if (_item === "零") {_item = "";_level = "";// 否則如果末尾為零字,則去掉這個零字} else if (_item[_item.length - 1] === "零") {_item = _item.slice(0, _item.length - 1);}return pre + _item + _level;}, "");// 小數部分let _decimal = decimal.map((item, idx) => {const unit = confs.decimal.unit;const _unit = item !== "0" ? unit[unit.length - idx - 1] : "";return `${conf.num[item]}${_unit}`;}).join("");// 如果是整數,則補個整字return `${_integer}元` + (_decimal || "整"); };總結
以上是生活随笔為你收集整理的js如何实现阿拉伯数字转中文大写数字的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 百会ZOHO发布基于SaaS面向中小企业
 - 下一篇: Javascript之把网页加入收藏夹功