zwsz
Version:
转换混合的中英文,支持阿拉伯数字、中文数字、会计数字转换为数字。这个项目是[emp-script-static]https://github.com/gdx1231/emp-script-static的一部分,分出来作为独立项目使用。
295 lines (271 loc) • 8.01 kB
JavaScript
(function (global, factory) {
if (typeof module === "object" && typeof module.exports === "object") {
module.exports = factory();
} else {
factory(global);
}
})(typeof window !== "undefined" ? window : this, function (global) {
let chnNumChar = {
'零': 0, '0': 0, "0": 0, 'o': 0, 'O': 0,
'一': 1, '壹': 1, '1': 1, "1": 1,
'二': 2, '贰': 2, '2': 2, "2": 2, '两': 2, '俩': 2,
'三': 3, '叁': 3, '3': 3, "3": 3,
'四': 4, '肆': 4, '4': 4, "4": 4,
'五': 5, '伍': 5, '5': 5, "5": 5,
'六': 6, '陆': 6, '6': 6, "6": 6,
'七': 7, '柒': 7, '7': 7, "7": 7,
'八': 8, '捌': 8, '8': 8, "8": 8,
'九': 9, '玖': 9, '9': 9, "9": 9
};
let chnNameValue = {
'十': { value: 10, first: true },
'拾': { value: 10, first: true },
'什': { value: 10, first: true },
'百': { value: 100 },
'佰': { value: 100 },
'陌': { value: 100 },
'千': { value: 1000 },
'阡': { value: 1000 },
'仟': { value: 1000 },
'k': { value: 1000, stop: true },
'K': { value: 1000, stop: true },
'万': { value: 10000, stop: true },
'萬': { value: 10000, stop: true },
'w': { value: 10000, stop: true },
'W': { value: 10000, stop: true },
'M': { value: 1000 * 1000, stop: true }, // million
'm': { value: 1000 * 1000, stop: true },
'亿': { value: 100000000, stop: true },
'b': { value: 1000 * 1000 * 1000, stop: true }, //billion
'B': { value: 1000 * 1000 * 1000, stop: true }
};
let negatives = {
'-': true,
'负': true,
'-': true
};
let positives = {
'+': true,
'正': true
};
let skipTails = {
'整': true
};
function newPart() {
return { number: 0, scale: 1, items: [] };
}
function convertToParts(strs) {
let parts = [newPart()];
let prevName = null;
for (let i = 0; i < strs.length; i++) {
let alpha = strs[i];
let name = chnNameValue[alpha];
let num = chnNumChar[alpha];
parts[parts.length - 1].items.push([alpha, name, num]);
if (name) {
if ((i == 0) && name.first) { //十
let number = 10;
parts[parts.length - 1].number = number;
} else if (name.stop) {
parts[parts.length - 1].scale = name.value || 1;
// 创建新的片段
parts.push(newPart());
scale = 1;
prevName = null;
} else {
if (i == strs.length - 1) {
console.log(name)
parts[parts.length - 1].number.scale = name.value;
}
prevName = name;
}
continue;
}
if (num == null) {
throw '非数字或单位:' + alpha;
}
num = (num);
let nextChar = i == strs.length - 1 ? null : strs[i + 1];
let nextName = i == strs.length - 1 ? null : chnNameValue[nextChar];
let nextNum = chnNumChar[nextChar];
if (nextName && nextName.stop) {
nextName = null;
}
let lastNum = parts[parts.length - 1].number;
let number;
let items = parts[parts.length - 1].items;
let itemPre = items[items.length - 2];//上一个
let itemPrePre = items[items.length - 3];// 上上个
if (nextName == null) {
if (prevName == null) {//连续的数字,例如 203
let skipTen = false;
if (itemPre && itemPre[2] === 0) {
if (itemPrePre && itemPrePre[1] != null/*是单位 */) {//捌仟零六 的零
skipTen = true;
}
} else if (itemPre && itemPre[1] && itemPre[1].value === 10) { //十六
skipTen = true;
}
if (skipTen) {
number = lastNum + num;
} else {
number = lastNum * 10 + num;
}
} else {// 例如 二千五,运算到五
if (itemPre && itemPre[1] && itemPre[1].value === 10 && (itemPrePre == null || itemPrePre[2] === 0 || itemPrePre[1] != null)) { //十六
number = lastNum + num + 10;
} else {
number = lastNum + num;
}
}
} else {
if (prevName == null) { // 例如 二千零五十
number = lastNum + num * (nextName.value);
} else {
number = lastNum + num * (nextName.value);
}
}
parts[parts.length - 1].number = number;
prevName = null;
//console.log(`num=${num}, number=${number}`);
}
//console.log(parts)
return parts;
}
function convertJflhNum(strs, alpha, loc) {
let fenv = strs[loc - 1];
let fenNum = chnNumChar[fenv];
if (!fenNum) {
return -1;
}
//一元=10角,一元=100分,一元=1000厘,一元=10000毫
if (alpha == '角') {
return ("0." + fenNum) * 1;
} else if (alpha == '分') {
return ("0.0" + fenNum) * 1;
} else if (alpha == '厘') {
return ("0.00" + fenNum) * 1;
} else if (alpha == '毫') {
return ("0.000" + fenNum) * 1;
} else {
return -1;
}
}
function convertJflh(strs) { // 角分厘毫
let sum = 0;
let inc = 0;
for (let i = strs.length - 1; i >= 0; i -= 2) {
let alpha = strs[i];
let num = convertJflhNum(strs, alpha, i);
if (num === -1) {
break;
} else {
sum += num;
inc++;
}
}
return {
sum: sum,
inc: inc,
strs: strs.splice(0, strs.length - inc * 2)
};
}
/**
* 处理整数部分
* @param {*} strs 字符串
* @returns 整数
*/
function convert(strs) {
let jiaofen = convertJflh(strs);
// console.log(jiaofen);
strs = jiaofen.strs;
let parts = convertToParts(strs);
let last = 0;
let scale1 = 1;
for (let i = parts.length - 1; i >= 0; i--) {
let part = parts[i];
let p = part.number;
scale1 = scale1 * part.scale;
last += p * scale1;
}
return last + jiaofen.sum;
}
/**
* 处理·小数部分
* @param {*} strs 字符串
* @returns 小数
*/
function convertDot(strs) {
let scale = 1;
let skip = 0;
for (let i = strs.length - 1; i >= 0; i--) {
let alpha = strs[i];
let name = chnNameValue[alpha]; // 结尾的连续单位,例如 0.35百万
if (!name) {
break;
}
scale *= name.value;
skip++;
}
let newStrs = scale == 1 ? strs : strs.splice(0, strs.length - skip);
let parts = convertToParts(newStrs);
let last = 0;
let scale1 = 1;
for (let i = parts.length - 1; i >= 0; i--) {
let part = parts[i];
let p = part.number;
scale1 = scale1 * part.scale;
last += p * scale1;
}
let last1 = ("0." + last) * 1;
return [last1, scale, newStrs.length];
}
function chineseToNumber(chnStr) {
if (!chnStr) {
return chnStr;
}
if (!isNaN(chnStr.toString())) {
return chnStr.toString() * 1;
}
let chnStrs = chnStr.replace(/,|,| |元|圆/ig, '').replace(/点|。/ig, '.').split('.');
if (chnStrs.length > 2) {
throw '非数字表达式:' + chnStr;
}
let strs = chnStrs[0].split('');
let dots = (chnStrs.length == 2 ? chnStrs[1] : "").split('');
let isNegative = false;
let alpha = strs[0];
if (negatives[alpha]) { // 负,-
isNegative = true;
strs = strs.splice(1);
} else if (positives[alpha]) { // 正,+
isNegative = false;
strs = strs.splice(1);
}
let lastAlpha = strs[strs.length - 1];
if (skipTails[lastAlpha]) { //整
strs = strs.splice(0, strs.length - 1);
} else if (dots.length > 1) {
lastAlpha = dots[dots.length - 1];
if (skipTails[lastAlpha]) { //整
dots = dots.splice(0, dots.length - 1);
}
}
let number = convert(strs); //
let number1 = dots.length > 0 ? convertDot(dots) : 0;
if (number1 == 0) { // 没有小数
return number * (isNegative ? -1 : 1);
}
// console.log(number, number1)
let fixed = number1[2] < 0 ? 0 : number1[2];
let scale = number1[1];
return ((number + number1[0]) * scale).toFixed(fixed) * (isNegative ? -1 : 1);
}
if (typeof window != 'undefined' && window.EWA && window.EWA_Utils) {
window.EWA_Utils.chineseToNumber = chineseToNumber;
} else if (global) {
global.chineseToNumber = chineseToNumber;
} else {
return chineseToNumber;
}
});