基于JavaScript编写一个简易的数字转中文功能
作者:剪刀石头布啊
前言
今天我们写一个一个简易的数字转中文的效果,虽然是功能看起来很简单,但是要是没有写过这类功能的话,那么可能会无从下手,下面就简单讲一下写这类逻辑的过程
思路
实现简易思路:
- 大单位是以万、亿、兆等为单位的,4位小数一组,因此需要对数字进行四位一组分组操作,在后面追加单位即可
- 除了大单位,中间的小单位则是个十百千,基本都是一致,因此使用同一种统一处理方案,其中个位没有单位
- 除了单位还有每一位数字的翻译工作,即:
0~9=>零~九 - 淡出处理中文语法中特有的情况,例如:开头不显示一十而是十,零中间作为间隔只能有一个,连续的零没有大单位,以及各位为零的处理等
- 入参处理(这里简单处理一下)
代码实现
//数字转中文(要支持小数,可以在扩展,小数就比较简单了)
//入参为数字,因此不考虑开头为零的情
const convertChineseNumber = (number) => {
if (isNaN(number)) return "NAN";
const units = ["", "万", "亿", "兆", "京", "垓"];
const baseUnits = ["", "十", "百", "千"];
const cNumbers = ["零", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
//分割四位一组,反转数组,从后往前加单位
const numGroup = String(number)
.replace(/\B(?=(\d{4})+$)/g, " ") //使用前瞻运算符来处理四位一体
.split(" ")
.reverse();
let result = "";
//遍历从后往前加单位
numGroup.forEach((numStrings, idx) => {
//处理全零的情况,不应该带单位,由于需要间隔0的情况,保留一个零
if (numStrings === "0000") {
result = '零' + result
return;
}
//有数的先添加大单位
result = units[idx] + result;
//分割四位一组的小数字,仍然是反转,从后往前加单位
numStrings
.split("")
.reverse()
.forEach((item, idx) => {
//处理每个后面的单位,其中个位没有单位,0也没有单位
if (idx !== 0 && item !== "0") {
result = baseUnits[idx] + result;
}
//数字翻译
result = cNumbers[Number(item)] + result;
});
});
//处理结果中可能存在的中文读写问题,例如不会存在连续的零,开头不会一十
//零后面不应该有单位,非零整数结尾不会读零
return result
.replace(/零+/g, "零")
.replace(/^(一十)/, "十")
.replace(new RegExp(`零([${units.join("")}]{1})`, "g"), "$1") //小单位处理了大单位也要处理
.replace(/(.+)零$/, "$1")
};
测试案例
//我们试验几个案例 const numbers = [ convertChineseNumber(0), convertChineseNumber(1234567899), convertChineseNumber(101234567899), convertChineseNumber(100234567899), convertChineseNumber(101034567899), convertChineseNumber(101030067899), convertChineseNumber(101030067890), convertChineseNumber(101030007899), convertChineseNumber(100000007899), convertChineseNumber(100070007899), convertChineseNumber(100007007899), ]; console.log(numbers); //目前来看返回结果是对的,如果感觉哪里不对,可以在填填补补就行了 [ '零', '十二亿三千四百五十六万七千八百九十九', '一千零一十二亿三千四百五十六万七千八百九十九', '一千零二亿三千四百五十六万七千八百九十九', '一千零一十亿三千四百五十六万七千八百九十九', '一千零一十亿三千零六万七千八百九十九', '一千零一十亿三千零六万七千八百九十', '一千零一十亿三千万七千八百九十九', '一千亿零七千八百九十九', '一千亿七千万七千八百九十九', '一千亿零七百万七千八百九十九' ]
知识扩展
下面小编为大家整理了一些其他js实现数字转中文的方法,希望对大家有所帮助
1.js如何实现阿拉伯数字转中文大写数字
/**
* @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 || "整");
};
2.js实现万亿数字转中文
思路:首先创建一个函数,它的主要功能是将一个输入的阿拉伯数字(如 1234)转换为对应的中文数字(如 "一千二百三十四")。这个过程包括了数字与中文字符的映射、单位的正确拼接以及一些特殊情况的处理,比如零的情况。
具体实现:
1. 数字与中文的映射
首先,定义两个数组:
const chineseNumbers = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; const units = ['', '十', '百', '千', '万', '十万', '百万', '千万', '亿', '十亿', '百亿', '千亿', '万亿'];
chineseNumbers数组包含了数字 0 到 9 对应的中文字符。units数组包含了中文数字的单位,如 "十"、"百"、"千"、"万"、"亿" 等。
当输入的数字逐位转换时,每个位数字会映射为 chineseNumbers 中的对应字符,而每一位的单位则是通过 units 数组中的单位进行拼接。
2. 处理特殊情况:数字为零
在中文中,数字零有着特殊的语法规则。多个零不能连续出现,且如果数字的最后一位是零,则最终输出时不应再添加“零”。因此,代码中引入了 zeroFlag 标志,用来表示是否已经遇到零:
let zeroFlag = false; // 是否在零的位置
当遍历到零时,如果之前已经添加过零,则跳过该零,否则就把“零”添加到字符串中,并将 zeroFlag 设置为 true,表示后续的零就不再重复添加。
3. 数字转换的核心部分
通过以下代码,数字逐位从右向左进行拆解:
while (num > 0) {
let part = num % 10;
if (part === 0) {
if (!zeroFlag) {
str = chineseNumbers[0] + str; // 添加“零”
zeroFlag = true;
}
} else {
str = chineseNumbers[part] + units[unitPos] + str;
zeroFlag = false;
}
num = Math.floor(num / 10); // 去除个位数字
unitPos++; // 移动到下一个单位
}
- 在循环中,每次通过
num % 10获取数字的最后一位,并使用chineseNumbers[part]将数字转换为中文字符。 - 如果该位数字为零,则检查是否需要添加“零”。如果零还没有添加过,则将“零”添加到结果字符串中。
- 非零数字会被转换成相应的中文字符,并根据当前的单位(
units[unitPos])进行拼接。例如,个位的数字会拼接“”,十位数字会拼接“十”,百位数字会拼接“百”,依此类推。
每次处理完一位数字后,使用 Math.floor(num / 10) 将数字向右移一位,并且单位位置 unitPos 增加 1,指向下一个单位。
4. 处理 “十”的特殊情况
在中文数字中,对于 10 到 19 之间的数字,不需要在“十”前面加上“一”。例如,数字 15 应该转换为“十五”而不是“一十五”。为了解决这个问题,代码中加入了以下判断:
if (str.startsWith('一十')) {
str = str.substring(1);
}
这段代码会检查转换后的字符串是否以“十”开头(即是否是10~19之间的数字),如果是的话,直接去掉前面的“一”,生成正确的中文形式。
5.函数的返回值
最终,函数返回的是经过转换后的中文数字:
str = str.replace(/零$/, '');//去掉末尾的零 return str;
现在还有个问题,如果数太大会出现单位重复的问题,例如,数字 1110016543 应该是 十一亿一千零一万六千五百四十三 而不是 十亿一亿一千万零一万六千五百四十三,解决这个问题我们需要写一个处理函数。
6.处理函数
function handelr(str) {
let lastW = str.lastIndexOf('万');// 获取字符串中最后一个“万”字符的位置
let len = str.length;
let temp='', temp2='', flagw='';//用于暂存处理后的字符串和于标记是否遇到“万亿”
// 判断字符串中包含"万亿"改变标记状态
if (str.indexOf('万亿') > 0) {
flagw = true;
}
//遍历字符串去除多余‘万'字
for (let i = 0; i < len; i++) {
if (i == lastW) {
temp = temp.concat(str[i]);
}
//判断是否保留第一个'万'字
if (str[i] == '万') {
if (!flagw) {
continue;
}
flagw = false;
}
temp = temp.concat(str[i]);
}
//处理多余的'亿'字
let len2 = temp.length;
let lasty = temp.lastIndexOf('亿');
for (let j = 0; j < len2; j++) {
if (j == lasty) {
temp2 = temp2.concat(temp[j]);
}
if (temp[j] == '亿') {
continue;
}
temp2 = temp2.concat(temp[j]);
}
return temp2;// 返回最终的处理结果
}
最后
上面的整体思路还是可以得,实际还是有所欠缺的,例如:不支持小数,对于大数字的单位支持也不够多,甚至一些读法的场景可能考虑还不够完善
需要完善的话,实际按照上面思路补充一下就行了
到此这篇关于基于JavaScript编写一个简易的数字转中文功能的文章就介绍到这了,更多相关JavaScript数字转中文内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
