数字转大写一般情况下有两种常用的场景:
1、数字转小写文字序号,比如: 16 -> 一十六 ; 123 -> 一百二十三
2、金额转大写,比如 11.11 -> 拾壹元壹角壹分
符合以上两种情况的请随意享用
需要掌握基础的数组处理方法,比如splice跟slice,以及正则表达式的基本操作,参考
Array.prototype.splice() - JavaScript | MDN (mozilla.org);
正则表达式 - JavaScript | MDN (mozilla.org)
场景一:数字转小写文字序号
/*数字转小写文字序号 eg: 16 -> 一十六 ; 123 -> 一百二十三*/
function numbertoUpper(numStr) {
//数值最大不超过1万亿
if (isNaN(numStr) || numStr >= 1000000000000) return "无效数字!";
// 11个数字单位,1万亿以内的数位按顺序从左到右对应排列
let sUnit = ["千","百","十","亿","千","百","十","万","千","百","十"];
//10个小写,以数字为索引取对应的大写(eg: sCapital[8] -> ‘八’)
let sCapital = ["零","一","二","三","四","五","六","七","八","九"];
sUnit.splice(0,sUnit.length - numStr.length + 1); //截取数位
let sOutput = "";
for (let i = 0, len = numStr.length; i < len; i++) {
//拼接数字跟数位
if (i === len - 1) {
sOutput += sCapital[Number(numStr.slice(i,i+1))];
} else {
sOutput +=sCapital[Number(numStr.slice(i, i + 1))] + sUnit.slice(i, i + 1);
}
}
return sOutput
.replace(/零[千百十]/g, "零")
.replace(/零{2,}/g, "零")
.replace(/零([亿|万])/g, "$1")
.replace(/亿零{0,3}万/, "亿")
.replace(/(\S+)零$/g, "$1");
}
场景二: 小写金额转化大写金额
第一种实现: 将金额数跟数位对应起来,一个for循环搞定,然后通过正则进行过滤,比较推荐这种
function amountLtoU(amount) {
//数值最大不超过1万亿
if (isNaN(amount) || amount >= 1000000000000) return "无效金额!";
//将负号‘-’显示成汉字‘(负)’
let sPrefix = amount < 0 ? "(负)" : "";
// 当传入的金额没有经过科学计算保留两位小数的话,则用四舍五入进行处理
amount = Math.round(amount*100)/100;
//格式化成两位小数格式(两位小数对应“'角”和“分”)
let sAmount = Math.abs(amount).toFixed(2);
// 14个数字单位,1万亿以内的数位按顺序从左到右对应排列
let sUnit = ["仟","佰","拾","亿","仟","佰","拾","万","仟","佰","拾","元","角","分"];
// 10个大写数字,以数字为索引取对应的大写(eg: sCapital[8] -> ‘捌’)
let sCapital = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
//去除小数点(使数字与数位对应)
sAmount = sAmount.replace(".", "");
//截取当前传入金额对应的数位集合
sUnit.splice(0,sUnit.length - sAmount.length);
let sOutput = "";
for (let i = 0, len = sAmount.length; i < len; i++) {
//拼接大写数字与数位
sOutput +=
sCapital[Number(sAmount.slice(i, i+1))] + sUnit[i];
}
// 返回的时候用正则过滤掉零千、零百、零万等情况
return (
sPrefix +
sOutput
.replace(/零角零分$/, "整")
.replace(/零[仟佰拾]/g, "零")
.replace(/零{2,}/g, "零")
.replace(/零([亿|万])/g, "$1")
.replace(/零+元/, "元")
.replace(/亿零{0,3}万/, "亿")
.replace(/^元/, "零元")
);
}
还有第二种实现:这种方式的,是拆分整数跟小数,分开解析,稍显麻烦
function digitToUpper(num) {
let fraction = ["角", "分"];
let digit = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"];
let unit = [
["元", "万", "亿"],
["", "拾", "佰", "仟"],
];
let head = num < 0 ? "欠" : "";
num = Math.abs(num);
let out = ""; // 输出
// 提取小数点后两位 角 分
for (let i = 0; i < fraction.length; i++) {
out += (
digit[Math.floor(num * 10 * Math.pow(10, i)) % 10] + fraction[i]
).replace(/零./, "");
}
// 小数点后两位是0,标识为“整”
out = out || "整";
// 向下取整数
num = Math.floor(num);
for (let i = 0; i < unit[0].length && num > 0; i++) {
let p = "";
for (let j = 0; j < unit[1].length && num > 0; j++) {
// 依次取出最低位数进行大写数字转换,并拼接上单位
p = digit[num % 10] + unit[1][j] + p;
num = Math.floor(num / 10);
}
out = p.replace(/(零.)*零$/, "").replace(/^$/, "零") + unit[0][i] + out;
}
return (
head +
out
.replace(/(零.)*零元/, "元")
.replace(/(零.)+/g, "零")
.replace(/^整$/, "零元整")
);
}
如果以上方案还不满足,可以评论区提出需求,一起讨论交流