当涉及到前端的财务模块有关的时候,比如列表展示、导出、打印发票报表等场景时,我们需要把金额转换为人民币大写
比如:数字:108.12 => 人民币大写:壹佰零捌元壹角贰分
一 | 二 | 三 | 四 | 五 | 六 | 七 | 八 | 九 | 十 | 百 | 千 | 万 | 亿 | 元 | 角 | 分 | 零 | 整 |
壹 | 贰 | 叁 | 肆 | 伍 | 陆 | 柒 | 捌 | 玖 | 拾 | 佰 | 仟 | 万 | 亿 | 圆 | 角 | 分 | 零 | 整 |
这里有5种常见的方法,逐一介绍如下:
1.递归转换法:
这是一种比较复杂的方法,在每一个单位级别都需要进行递归转换。流程如下:
function convertToRMB(amount) {
const units = ['元', '十', '百', '千', '万', '十万', '百万', '千万', '亿', '十亿', '百亿', '千亿'];
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
function convert(num) {
if (num === 0) {
return '';
}
let str = '';
if (num < 10) {
str = digits[num];
} else if (num < 20) {
str = '十' + digits[num - 10];
} else if (num < 100) {
str = digits[Math.floor(num / 10)] + '十' + digits[num % 10];
} else {
str = digits[Math.floor(num / 100)] + '百' + convert(num % 100);
}
return str;
}
const [integerPart, decimalPart] = String(amount).split('.');
const integerInRMB = convert(parseInt(integerPart));
let result = integerInRMB + '元';
if (decimalPart) {
result += decimalPart.split('').map(digit => digits[digit]).join('') + '角';
}
return result;
}
console.log(convertToRMB(108.12)); //壹百捌元壹贰角
2.查表转换法:
这种方法相对简单,事先准备好一个金额与大写的对应表。流程如下:
将金额转换为字符串,并按位拆分为一个数组。
从高位到低位,根据数组中的每一位查表并拼接对应的大写数字(例如0-9对应的大写数字为"零"、“壹”、"贰"等)。
根据小数点位置,对整数部分和小数部分进行拼接。
function convertToRMB(amount) {
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
const units = ['', '拾', '佰', '仟', '万', '拾万', '佰万', '仟万', '亿', '拾亿', '佰亿', '仟亿'];
const [integerPart, decimalPart] = String(amount).split('.');
const integerDigits = integerPart.split('').map(digit => digits[parseInt(digit)]);
let result = '';
for (let i = 0; i < integerDigits.length; i++) {
result += integerDigits[i] + units[integerDigits.length - 1 - i];
}
if (decimalPart) {
const decimalDigits = decimalPart.split('').map(digit => digits[parseInt(digit)]);
result += '点' + decimalDigits.join('');
}
return result;
}
console.log(convertToRMB(108.12)); //壹佰零拾捌点壹贰
3.数学计算法:
这种方法相比前两种方法更简洁,通过数学计算直接得出结果。流程如下:
将金额保留两位小数,并转换为数值型。
获取整数部分和小数部分。
将整数部分进行数学计算得到相应的大写数字。
将小数部分转换为对应的大写数字。
function convertToRMB(amount) {
const digits = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
const [integerPart, decimalPart] = String(amount.toFixed(2)).split('.');
const integerDigits = integerPart.split('').map(digit => digits[parseInt(digit)]);
let result = '';
for (let i = 0; i < integerDigits.length; i++) {
result += integerDigits[i];
}
if (decimalPart) {
const decimalDigits = decimalPart.split('').map(digit => digits[parseInt(digit)]);
result += '点' + decimalDigits.join('');
}
return result;
}
console.log(convertToRMB(108.12)); //壹零捌点壹贰
4.第3方库的使用:
这是最简单的方法,通过使用前端开发中已经存在的金额转换函数库来实现。流程如下:
在前端项目中引入合适的金额转换函数库。
调用相应的函数传入金额参数,即可得到转换结果。但是呢需要下包,常言鱼与熊掌不可兼得
4.1安装number-to-chinese-words
npm install number-to-chinese-words
使用:
var converter = require('number-to-chinese-words');
converter.toOrdinal(108.12);
将数字转为文字:toWords(number)
// 整數:
var converter = require('number-to-chinese-words');
converter.toWords(13); // => “十三”
// Decimal numbers:
converter.toWords(2.9); // => “二點九”
// Negative numbers:
converter.toWords(-3); // => "負三"
// Large numbers:
converter.toWords(9007199254740992); // => “九千零七兆一千九百九十二億五千四百七十四萬零九百九十二
将整数转换成文字:toWordsOrdinal(number)
但是会在原来的基础上再加上前置的「第」字。 如果输入的数字包含小数点,小数点后的数目将会被移除。
import converter from "number-to-chinese-words";
converter.toWordsOrdinal(21); // => “第二十一”
转大写:
var converter = require("number-to-chinese-words")
converter.default.labels = Object.assign({},converter.default.labels, {
digits : ['零','壹', '貳', '參', '肆', '伍', '陸', '柒', '捌', '玖'],
units: ['','拾', '佰', '仟', '萬', '拾', '佰', '仟', '億', '拾', '佰', '仟', '兆', '拾', '佰', '仟', '京', '拾', '佰', '仟', '垓']
})
converter.toWords(199254740992);
// => 壹仟玖佰玖拾貳億伍仟肆佰柒拾肆萬零玖佰玖拾貳
4.2、安装pixiu-number-toolkit(推荐)
pixiu-number-toolkit是一个用TypeScript编写的数字工具集,提供了一组用于数字转换、财务计算、格式化和数学运算的函数。其中就包含了一个名为digitUppercase的函数,可以将数字金额转换为大写的人民币汉字表示。
安装
npm install pixiu-number-toolkit
使用digitUppercase函数进行转换:
import { digitUppercase } from "pixiu-number-toolkit";
const amount = 1234.56;
const result = digitUppercase(amount);
console.log(result);
// 输出: "壹仟贰佰叁拾肆元伍角陆分"
这个函数还可以处理负金额,在结果前加上“欠”。零金额表示为“零元整”。
5.还有一种(推荐):
function transformStr(money) {
var cnMoney = "零元整";
var strOutput = "";
var strUnit = '仟佰拾亿仟佰拾万仟佰拾元角分';
money += "00";
var intPos = money.indexOf('.');
if (intPos >= 0) {
money = money.substring(0, intPos) + money.substr(intPos + 1, 2);
}
strUnit = strUnit.substr(strUnit.length - money.length);
for (var i = 0; i < money.length; i++) {
strOutput += '零壹贰叁肆伍陆柒捌玖'.substr(money.substr(i, 1), 1) + strUnit.substr(i, 1);
}
cnMoney = strOutput.replace(/零角零分$/, '整').replace(/零[仟佰拾]/g, '零').replace(/零{2,}/g, '零').replace(/零([亿|万])/g, '$1').replace(/零+元/, '元').replace(/亿零{0,3}万/, '亿').replace(/^元/, "零元");
return cnMoney;
}
// 108.12 => 壹佰零捌元壹角贰分