1.浮动运算
解决浮动运算问题,避免小数点后产生多位数和计算精度损失。
1.1 获取当前数小数位的长度
// 获取当前数小数位的长度(处理科学计数法,本质上处理e-n的情况)
function digitLength(num) {
const eSplit = num.toString().split(/[eE]/);
const len = (eSplit[0].split('.')[1] || '').length - (+eSplit[1] || 0);
return len > 0 ? len : 0;
}
1.2 把小数转成整数
// 把小数转成整数,支持科学计数法。如果是小数则放大成整数
function float2Fixed(num) {
if (+num.toString().indexOf('e')) {
return Number(num.toString().replace('.', ''));
}
const dlen = digitLength(num);
return dlen > 0 ? num * (window as any).Math.pow(10, dlen) : num;
}
1.3 精确乘法
function multiply(...others: number[]) {
if (others.length > 1) {
const num1 = others.shift();
const num2 = others.shift();
if (others.length > 0) {
return multiply(multiply(num1, num2), ...others);
}
const num1Changed = float2Fixed(num1);
const num2Changed = float2Fixed(num2);
// 把两个数的小数位数相加
const baseNum = digitLength(num1) + digitLength(num2);
const leftValue = num1Changed * num2Changed;
return leftValue / (window as any).Math.pow(10, baseNum);
}
return others[0] || 0;
}
1.4 精确加法
function add(...others) {
if (others.length > 1) {
const num1 = others.shift();
const num2 = others.shift();
if (others.length > 0) {
return add(add(num1, num2), ...others);
}
const baseNum = (window as any).Math.pow(
10,
(window as any).Math.max(
digitLength(num1),
digitLength(num2),
),
);
return (
(multiply(num1, baseNum) + multiply(num2, baseNum)) / baseNum
);
}
return others[0] || 0;
}
1.5 精确乘法
function subtract(...others) {
if (others.length > 1) {
const num1 = others.shift();
const num2 = others.shift();
if (others.length > 0) {
return subtract(subtract(num1, num2), ...others);
}
const baseNum = (window as any).Math.pow(
10,
(window as any).Math.max(
digitLength(num1),
digitLength(num2),
),
);
return (
(multiply(num1, baseNum) - multiply(num2, baseNum)) / baseNum
);
}
return others[0] || 0;
}
1.6 精确除法
function divide(...others) {
if (others.length > 1) {
const num1 = others.shift();
const num2 = others.shift();
if (others.length > 0) {
return divide(divide(num1, num2), ...others);
}
const num1Change = float2Fixed(num1);
const num2Change = float2Fixed(num2);
return multiply(
num1Change / num2Change,
(window as any).Math.pow(
10,
digitLength(num2) - digitLength(num1),
),
);
}
return others[0] || 0;
}
1.7 四舍五入
// 四舍五入,且保留小数
function round(num, ratio = 0) {
const base = (window as any).Math.pow(10, ratio);
return divide(
(window as any).Math.round(multiply(num, base)),
bas
);
}
1.8 将数据转换为大写
function transferIntoBigNum(num: number): string {
const strNum: string = (num + '').replace(/^[\s0]+|\s+$/gi, '');
const mapBigNum: string[] = ['〇','一','二','三','四','五','六','七','八','九','十',];
const mapDw: string[] = ['个','十','百','千','万','十万','百万','千万','亿',];
if (num <= 10) {
return mapBigNum[num || 0];
}
const result: string[] = [];
for (let i = 0, l = strNum.length, j = l - 1; i < l; i++, j--) {
if (+strNum[i] === 0) {
if (result[result.length - 1] !== '〇') {
result.push(mapBigNum[0]);
}
} else {
result.push(mapBigNum[strNum[i]]);
}
if (j > 0 && result[result.length - 1] !== '〇') {
result.push(mapDw[j]);
}
}
let index: number = result.length;
while (index--) {
if (result[index] === '〇') {
result.pop();
} else if (result[index] === '十') {
if (num > 100 && num < 1000) {
result.pop();
} else {
break;
}
} else {
break;
}
}
if (result[0] === '一' && result[1] === '十') {
result.shift();
}
return result.join('');
}