whychw
2021-01-08 826ecd914e7fa71f2ecbb6915d0dee2e94f62acb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
 * @数字计算方法
 * @author (zyk)
 * @returns 
 */
 
// 运算符
const operators = ['+', '-', '*', '/', '(', ')'];
// 运算符优先级
const priority = {
  ')': 30,
  '*': 20,
  '/': 20,
  '+': 10,
  '-': 10,
  '(': 0,
};
// 获取小数点位数
const calcPos = (num) => (num.toString().indexOf('.') > -1 ? num.toString().split('.')[1].length : 0);
// 忽略小数点转为整数
const parseNum = (num) => parseInt(num.toString().replace('.', ''));
 
const FC = {
  // 加
  _add: (n1, n2) => {
    const p1 = calcPos(n1);
    const p2 = calcPos(n2);
    const m = Math.pow(10, Math.max(p1, p2));
    return (FC._mul(n1, m) + FC._mul(n2, m)) / m;
  },
  add: (...nums) => {
    let result = nums[0];
    for (let i = 1; i < nums.length; i++) result = FC._add(result, nums[i]);
    return result;
  },
  // 减
  _sub: (n1, n2) => FC.add(n1, -n2),
  sub: (...nums) => {
    let result = nums[0];
    for (let i = 1; i < nums.length; i++) result = FC._sub(result, nums[i]);
    return result;
  },
  // 乘
  _mul: (n1, n2) => {
    const p1 = calcPos(n1);
    const p2 = calcPos(n2);
    const m = Math.pow(10, p1 + p2);
    return (parseNum(n1) * parseNum(n2)) / m;
  },
  mul: (...nums) => {
    let result = nums[0];
    for (let i = 1; i < nums.length; i++) result = FC._mul(result, nums[i]);
    return result;
  },
  // 除
  _div: (n1, n2) => {
    const p1 = calcPos(n1);
    const p2 = calcPos(n2);
    const m = Math.pow(10, p2 - p1);
    return FC.mul(parseNum(n1) / parseNum(n2), m);
  },
  div: (...nums) => {
    let result = nums[0];
    for (let i = 1; i < nums.length; i++) result = FC._div(result, nums[i]);
    return result;
  },
  // 表达式计算
  calc: (expression) => {
    // 转化为表达式数组
    operators.map((op) => (expression = expression.split(op).join(`,${op},`)));
    const eArr = expression.split(',').filter((item) => item !== '');
 
    // 中缀转后缀
    const ops = [];
    const result = [];
    for (const item of eArr) {
      // 是操作符
      if (operators.includes(item)) {
        // 操作符栈为空 直接入栈
        if (ops.length === 0) ops.push(item);
        else {
          // 左括号 直接入栈
          if (item === '(') ops.push(item);
          // 右括号 匹配括号
          else if (item === ')') {
            let top = ops.pop();
            while (top !== '(') {
              result.push(top);
              top = ops.pop();
            }
          }
          // 加减乘除
          else if (priority[item] > priority[ops[ops.length - 1]]) ops.push(item);
          else {
            while (
              ops.length > 0 &&
              priority[item] <= priority[ops[ops.length - 1]]
            ) {
              const top = ops.pop();
              result.push(top);
            }
            ops.push(item);
          }
        }
      }
      // 是数字
      else {
        result.push(item);
      }
    }
    // 多余运算符推入结果栈
    while (ops.length > 0) result.push(ops.pop());
 
    // 后缀表达式计算
    const nums = [];
    // let r = 0;
    for (const item of result) {
      // 是运算符
      if (operators.includes(item)) {
        const num2 = nums.pop();
        const num1 = nums.pop();
        if (item === '+') nums.push(FC._add(num1, num2));
        if (item === '-') nums.push(FC._sub(num1, num2));
        if (item === '*') nums.push(FC._mul(num1, num2));
        if (item === '/') nums.push(FC._div(num1, num2));
      } else {
        nums.push(item);
      }
    }
    return nums[0];
  },
};
 
export default FC;