math.js文档地址:mathjs.org/docs/index.…
import * as math from 'mathjs'
class mathPlugin {
static install(Vue) {
Vue.prototype.$math={}
/**
* @param string expression 表达式
* @param number length 返回的小数位
* @param boolean roundUp 是否四舍五入,默认四舍五入
* @returns
*/
Vue.prototype.$math._eval = (expression,length,roundUp) => {
length = length || 0
roundUp = roundUp || false;
const regex = /(\d+(\.\d+)?|\+|\-|\*|\/|\(|\))/g;
let str = removeSpaces(expression); // 调用 removeSpaces 方法去掉空格
const matchs = str.match(regex);
const stack = [];
const output = [];
const operatorPriority = {
'+': 1,
'-': 1,
'*': 2,
'/': 2,
};
for (let i = 0; i < matchs.length; i++) {
const token = matchs[i];
if (token === '+' || token === '-' || token === '*' || token === '/') {
while (stack.length > 0 && operatorPriority[token] <= operatorPriority[stack[stack.length - 1]]) {
output.push(stack.pop());
}
stack.push(token);
} else if (token === '(') {
stack.push(token);
} else if (token === ')') {
while (stack.length > 0 && stack[stack.length - 1] !== '(') {
output.push(stack.pop());
}
stack.pop();
} else {
output.push(token);
}
}
while (stack.length > 0) {
output.push(stack.pop());
}
for (let i = 0; i < output.length; i++) {
const token = output[i];
if (token === '+' || token === '-' || token === '*' || token === '/') {
const num2 = stack.pop();
const num1 = stack.pop();
if (token === '+') {
stack.push(math.add(math.bignumber(Number(num1)),math.bignumber(Number(num2))));
} else if (token === '-') {
stack.push(math.subtract(math.bignumber(Number(num1)),math.bignumber(Number(num2))));
} else if (token === '*') {
stack.push(math.multiply(math.bignumber(Number(num1)),math.bignumber(Number(num2))));
} else if (token === '/') {
stack.push(math.divide(math.bignumber(Number(num1)),math.bignumber(Number(num2))));
}
} else {
stack.push(token);
}
}
if(length==0) return stack[0].toString();
return roundUp ? formatRound(stack[0].toString(),length) : formatNumber(stack[0].toString(),length);
}
/**
* toFixed是银行家舍入规则:
* 当要舍弃的数字是5时,如果5后面还有非零数字,则应该向上舍入;
* 如果5后面没有数字,或者后面都是0,则需要根据5前面的数字来判断
* 如果5前面的数字是偶数,则应该向下舍入;
* 如果5前面的数字是奇数,则应该向上舍入;
* @param number decimalPlaces 小数位数
* @param boolean roundUp 是否四舍五入,默认四舍五入
* @returns
*/
function ntoFixed (argNum,length,roundUp) {
roundUp = roundUp || false;
var num = parseFloat(argNum);
if (isNaN(num)) {
return 0;
}
var factor = Math.pow(10, length);
var truncated = 0;
if(roundUp){
truncated = Math.round(num * factor) / factor
}else{
truncated = Math.floor(num * factor) / factor
}
var str = truncated.toString();
var index = str.indexOf(".");
if (index === -1) {
if(length > 0) str += "."; // 添加小数点
}
var decimalIndex = str.indexOf(".");
var zerosToAdd = 0;
if(length!=0){
zerosToAdd = length - (str.length - 1 - decimalIndex);
}
for (var i = 0; i <zerosToAdd; i++) {
str += "0";
}
var diff = num - truncated;
if (roundUp && diff >= 0.5 / factor) {
str = (truncated + 1 / factor).toFixed(length);
}
return str;
}
//四舍五入
function formatRound(num,length) {
let str = ntoFixed(num,length); // 将数字保留指定位数小数
let dotIndex = str.indexOf("."); // 查找小数点位置
if (dotIndex === -1) { // 如果没有小数点
if(length > 0) str += "."; // 添加小数点
for (let i = 0; i < length; i++) { // 在末尾添加指定位数的0
str += "0";
}
} else { // 如果有小数点
let decimalPart = str.substr(dotIndex + 1); // 获取小数部分
let diff = length - decimalPart.length; // 计算需要添加的0的个数
for (let i = 0; i < diff; i++) { // 在小数部分末尾添加0
str += "0";
}
}
return str;
}
//字符串截取不四舍五入
function formatNumber(num, length) {
let str = num.toString(); // 将数字转换为字符串
let dotIndex = str.indexOf("."); // 查找小数点位置
if (dotIndex === -1) { // 如果没有小数点
if(length > 0) str += "."; // 添加小数点
for (let i = 0; i < length; i++) { // 在末尾添加指定位数的0
str += "0";
}
} else { // 如果有小数点
let decimalPart = str.substring(dotIndex + 1); // 获取小数部分
let diff = length - decimalPart.length; // 计算需要添加的0的个数
if (diff > 0) { // 如果需要添加0
for (let i = 0; i < diff; i++) { // 在小数部分末尾添加0
decimalPart += "0";
}
str = str.substring(0, dotIndex + 1) + decimalPart; // 拼接新的字符串
} else { // 如果需要截取小数部分
str = str.substring(0, dotIndex + length + 1); // 截取指定位数的小数部分
}
}
return str;
}
function removeSpaces(str) {
return str.replace(/\s+/g, '');
}
}
}
export default mathPlugin
推荐一个好用的正则表达式可视化网站 www.wangwl.net/static/proj…
todo:例外计算的的数字太大还是会变成科学计数法