This commit is contained in:
潘晓云
2022-03-10 11:20:21 +08:00
parent da3b427a77
commit 31cb7bd194
4 changed files with 355 additions and 103 deletions

View File

@ -0,0 +1,236 @@
/**
* 操作符类型运算符
* +:加法运算
* -:减法运算
* *:乘法运算
* /:除法运算
*/
type OperationType = '+' | '-' | '*' | '/';
class Big {
/**
* Big值
*/
private v: number;
/**
* 构造函数
* @param v 初始值
*/
constructor(v: number) {
this.v = v;
}
/**
* 转换整数,返回倍数及整数值,比如
* 100 >>> { times: 1, num: 100 } ===> 100
* 3.14 >>> { times: 100, num: 3.14} ===> 314
* @param n number
*/
private toInteger(n: number) {
const ret = { times: 1, num: 0 };
if (Number.isInteger(n)) {
ret.num = n;
return ret;
}
ret.times = Math.pow(10, n.toString().split('.')[1].length);
ret.num = parseInt((n * ret.times + 0.5).toString(), 10);
return ret;
}
/**
* 执行运算
* @param m 数值m
* @param n 数值n
* @param key 运算符
*/
private operation(m: number = 0, n: number = 0, key: OperationType) {
const o1 = this.toInteger(m);
const o2 = this.toInteger(n);
const n1 = o1.num;
const n2 = o2.num;
const t1 = o1.times;
const t2 = o2.times;
const max = Math.max(t1, t2);
let result = 0;
switch (key) {
case '+':
if (t1 === t2) {
// 两个小数位数相同
result = n1 + n2;
} else if (t1 > t2) {
// o1 小数位 大于 o2
result = n1 + n2 * (t1 / t2);
} else {
// o1 小数位 小于 o2
result = n1 * (t2 / t1) + n2;
}
result /= max;
break;
case '-':
if (t1 === t2) {
result = n1 - n2;
} else if (t1 > t2) {
result = n1 - n2 * (t1 / t2);
} else {
result = n1 * (t2 / t1) - n2;
}
result /= max;
break;
case '*':
result = (n1 * n2) / (t1 * t2);
break;
case '/':
result = (n1 * t2) / (t1 * n2);
break;
default:
result = 0;
}
return new Big(result);
}
/**
* 数值化
* @param n
*/
private numeric(n: number | Big) {
return n instanceof Big ? n.v : n;
}
/**
* 加法运算
* @param n
*/
public plus(n: number | Big) {
return this.operation(this.v, this.numeric(n), '+');
}
/**
* 减法运算
* @param n
*/
public minus(n: number | Big) {
return this.operation(this.v, this.numeric(n), '-');
}
/**
* 乘法运算
* @param n
*/
public multipliedBy(n: number | Big) {
return this.operation(this.v, this.numeric(n), '*');
}
/**
* 除法运算
* @param n
*/
public dividedBy(n: number | Big) {
return this.operation(this.v, this.numeric(n), '/');
}
/**
* 解析结果
*/
public parse() {
return this.v;
}
/**
* 小数点后固定指定位数比如固定小数点后5位数字则有
* 30 ==> 30.00000
* 3.14 ===> 3.14000
* @param n
*/
public static digits(v: number | Big, len: number = 2) {
if (Number.isInteger(v)) {
return `${v}.${Array(len).fill(0).join('')}`;
} else {
const [prefix, suffix] = v.toString().split('.');
const sLen = suffix.length;
if (sLen > len) {
return `${prefix}.${suffix.slice(0, len)}`;
} else if (sLen < len) {
return `${prefix}.${suffix}${Array(len - sLen)
.fill(0)
.join('')}`;
} else {
return `${prefix}.${suffix}`;
}
}
}
public digits(len: number) {
return Big.digits(this.v, len);
}
/**
* 人民币格式处理
* - 非数字返回0
* - 整数:直接返回
* - 小数:保留小数点后两位,超出两位则截取
* @param v
*/
public static rmb(v: string | number) {
if (isNaN(Number(v))) {
return '0';
} else {
const foo = v.toString();
if (/^[0-9]+$/.test(foo)) {
return foo;
} else {
const [prefix, suffix] = foo.split('.');
const sLen = suffix.length;
if (sLen > 2) {
return `${prefix}.${suffix.slice(0, 2)}`;
} else if (sLen < 2) {
return `${foo}0`;
} else {
return foo;
}
}
}
}
public rmb() {
return Big.rmb(this.v);
}
/**
* 切割数字
* @param v
*/
public static split(v: string | number) {
if (isNaN(Number(v))) {
return [];
} else {
return v
.toString()
.split('.')
.map((item, i) => {
if (i === 1) {
return item && item.length < 2 ? `${item}0` : item;
}
return item;
});
}
}
public split() {
return Big.split(this.v);
}
/**
* 省略 --> 如果超过1万则返回万制转换后小数点后保留两位
* 比如12345 返回 1.23万
* @param v
*/
public static ellipsis(v: string | number) {
// 如果不是数值类型并且转换之后不为数字,则直接返回传入值
if (isNaN(Number(v))) {
return v.toString();
}
// 如果传入数值小于1万则没必要转换直接返回
if (+v < 10000) {
return v.toString();
}
// 超过1万处理之后再返回
return Big.rmb(+v / 10000) + '万';
}
public ellipsis(v: string | number) {
return Big.ellipsis(this.v);
}
}
export default Big;