Forráskód Böngészése

[fix] 科学计数法计算错误和常数e混淆的问题
[update] 新增n次开方方法

Steven Yan 2 éve
szülő
commit
4df5675b6b
8 módosított fájl, 165 hozzáadás és 99 törlés
  1. 3 1
      .gitignore
  2. 18 17
      package.json
  3. 36 0
      scripts/build.sh
  4. 35 15
      src/app.js
  5. 5 2
      src/app.test.js
  6. 17 22
      src/calculator.js
  7. 33 41
      src/jison/calculator.jison
  8. 18 1
      src/test_cases.js

+ 3 - 1
.gitignore

@@ -13,4 +13,6 @@ core.*
 .idea/
 .vscode
 .env
-talos/dev.config.js
+talos/dev.config.js
+
+src/output

+ 18 - 17
package.json

@@ -1,19 +1,20 @@
 {
-  "name": "calc",
-  "version": "1.0.0",
-  "description": "",
-  "main": "app.js",
-  "scripts": {
-    "make": "cd src && jison jison/calculator.jison",
-    "start": "cd src && node app.js",
-    "test": "jest"
-  },
-  "author": "",
-  "license": "ISC",
-  "dependencies": {
-    "jison": "^0.4.18"
-  },
-  "devDependencies": {
-    "jest": "^29.7.0"
-  }
+    "name": "jison-calculator",
+    "version": "1.0.1",
+    "description": "",
+    "main": "app.js",
+    "scripts": {
+        "start": "cd src && node app.js",
+        "test": "jest",
+        "make": "cd src && jison jison/calculator.jison",
+        "build": "bash scripts/build.sh"
+    },
+    "author": "",
+    "license": "ISC",
+    "dependencies": {
+        "jison": "^0.4.18"
+    },
+    "devDependencies": {
+        "jest": "^29.7.0"
+    }
 }

+ 36 - 0
scripts/build.sh

@@ -0,0 +1,36 @@
+#!/bin/bash
+
+cd src
+
+mkdir -p ./output
+
+jison jison/calculator.jison -o output/calculator.mjs
+
+cat >> output/calculator.mjs << EOF
+
+
+export default {
+    parser: calculator,
+    Parser: calculator.Parser,
+    parse: function () {
+        return calculator.parse.apply(calculator, arguments);
+    },
+};
+EOF
+
+content=$(cat output/calculator.mjs)
+build_time=$(date '+%Y-%m-%d %H:%M:%S')
+
+cat > output/calculator.mjs << EOF
+/**
+ * @file calculator.mjs
+ * @description 高级计算器解析库
+ * @author Steven Yan
+ * @build $build_time
+ */
+
+EOF
+
+echo "$content" >> output/calculator.mjs
+
+echo -e "\n\033[7m========> Done. ========\033[0m\n"

+ 35 - 15
src/app.js

@@ -5,6 +5,9 @@ const {handlePrecision} = require('./utils.js');
 const parser = new calculator.Parser();
 
 function calc(exp, isDeg = false) {
+    exp = exp.replace(/E/g, 'e');
+    exp = exp.replace(/\be\b/g, 'Math.E');
+
     parser.parse(`isDeg(${isDeg * 1})`);
 
     const stack = [];
@@ -24,26 +27,43 @@ function calc(exp, isDeg = false) {
             if (res.length === 1 || !isNaN(resNum)) {
                 stack.push(resNum);
             } else {
-                // console.log(resNum, +parser.parse(resNum));
+                console.log(resNum, +parser.parse(resNum));
                 stack.push(parser.parse(resNum));
             }
             res = [];
         }
     }
+    const stackStr = stack.join('');
+    console.log(stackStr);
+    return handlePrecision(parser.parse(stackStr));
+}
+
 
-    return handlePrecision(parser.parse(stack.join('')));
+function print(tests) {
+    if (Array.isArray(tests)) {
+        const prints = [];
+        tests.forEach(v => {
+            let ans = '';
+            try {
+                ans = calc(v.value, v.isDeg);
+            } catch {
+                ans = 'Error';
+            }
+            const expect = String(v.result);
+            const o = {
+                isDeg: v.isDeg ? 1 : 0,
+                exp: v.value,
+                result: ans,
+                expect: expect,
+                correct: ans === expect,
+            };
+            prints.push(o);
+        });
+        console.table(prints);
+        return prints;
+    }
+    console.log(calc(tests));
+    return;
 }
 
-const prints = [];
-tests.forEach(v => {
-    const ans = +calc(v.value, v.isDeg);
-    const print = {
-        isDeg: v.isDeg ? 1 : 0,
-        exp: v.value,
-        result: ans,
-        expect: v.result,
-        correct: ans === v.result,
-    };
-    prints.push(print);
-});
-console.table(prints);
+print(tests);

+ 5 - 2
src/app.test.js

@@ -5,6 +5,9 @@ const {handlePrecision} = require('./utils.js');
 const parser = new calculator.Parser();
 
 function calc(exp, isDeg = false) {
+    exp = exp.replace(/E/g, 'e');
+    exp = exp.replace(/\be\b/g, 'Math.E');
+
     parser.parse(`isDeg(${isDeg * 1})`);
 
     const stack = [];
@@ -35,7 +38,7 @@ function calc(exp, isDeg = false) {
 }
 
 tests.forEach(v => {
-    test(`${v.value} = ${v.result} isDeg=${v.isDeg}`, () => {
-        expect(calc(v.value, v.isDeg)).toBe(v.result + '');
+    test(`isDeg=${v.isDeg ? 1: 0} ${v.value} = ${v.result}`, () => {
+        expect(calc(v.value, v.isDeg)).toBe(String(v.result));
     });
 });

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 17 - 22
src/calculator.js


+ 33 - 41
src/jison/calculator.jison

@@ -121,6 +121,7 @@ var dComp = function (v) {
     }
     return v;
 }
+
 %}
 
 /* lexical grammar */
@@ -128,33 +129,32 @@ var dComp = function (v) {
 %%
 
 \s+                   /* skip whitespace */
-[0-9]+("."[0-9]+)?("e""-"?[0-9]+)?\b  return 'NUMBER';
-"*"                   return '*';
-"×"                   return '*';
-"/"                   return '/';
-"÷"                   return '/';
-"-"                   return '-';
-"+"                   return '+';
-"^"                   return '^';
-"√"                   return 'SQRT';
-"sin"                 return 'sin';
-"tan"                 return 'tan';
-"cos"                 return 'cos';
-"atan"                return 'atan';
-"acos"                return 'acos';
-"asin"                return 'asin';
-"ln"                  return 'ln';
-"log"                 return 'log';
-"!"                   return '!';
-"isDeg"               return 'isDeg';
-"%"                   return '%';
-"("                   return '(';
-")"                   return ')';
-"π"                   return 'PI';
-"E"                   return 'EXP';
-"e"                   return 'E';
-<<EOF>>               return 'EOF';
-.                     return 'INVALID';
+[0-9]+("."[0-9]+)?("e""-"?"+"?[0-9]+)?\b  return 'NUMBER';
+"*"                                       return '*';
+"×"                                       return '*';
+"/"                                       return '/';
+"÷"                                       return '/';
+"-"                                       return '-';
+"+"                                       return '+';
+"^"                                       return '^';
+"√"                                       return 'SQRT';
+"sin"                                     return 'sin';
+"tan"                                     return 'tan';
+"cos"                                     return 'cos';
+"atan"                                    return 'atan';
+"acos"                                    return 'acos';
+"asin"                                    return 'asin';
+"ln"                                      return 'ln';
+"log"                                     return 'log';
+"!"                                       return '!';
+"isDeg"                                   return 'isDeg';
+"%"                                       return '%';
+"("                                       return '(';
+")"                                       return ')';
+"π"                                       return 'PI';
+"Math.E"                                  return 'Math.E';
+<<EOF>>                                   return 'EOF';
+.                                         return 'INVALID';
 
 /lex
 
@@ -183,7 +183,7 @@ e
         {$$ = -$2;}
     | NUMBER
         {$$ = Number(yytext);}
-    | 'E'
+    | 'Math.E'
         {$$ = Math.E;}
     | 'PI'
         {$$ = Math.PI;}
@@ -194,31 +194,23 @@ e
     | e '*' e
         {$$ = $1 * $3;}
     | e '/' e
-        {$$ = $1 / $3;}
+        {$$ = $1 / dComp($3);}
     | e '+' e
         {$$ = $1 + $3;}
     | e '-' e
         {$$ = $1 - $3;}
     | e '!'
-        {{
-          $$ = (
-            function fact(n) {
-                if (!Number.isSafeInteger(n)) {
-                    return n;
-                }
-                return n == 0 ? 1 : fact(n - 1) * n;
-            })($1);
-        }}
+        {{$$ = fac($1);}}
     | 'ln' e
         {$$ = Math.log($2);}
     | 'log' e
         {$$ = Math.log10($2);}
     | 'SQRT' e
-        {$$ = Math.sqrt($2);}
+        {$$ = $2 ** 0.5}
+    | e 'SQRT' e
+        {$$ = ($3) ** (1 / $1);}
     | 'isDeg' e
         {$$ = setIsDeg($2);}
-    | e 'EXP' e
-        {$$ = $1 * Math.pow(10, $3);}
     | 'sin' e
         {$$ = sin($2);}
     | 'cos' e

+ 18 - 1
src/test_cases.js

@@ -36,7 +36,7 @@ module.exports = [
         result: 1,
     },
     {
-        value: 'log(1 E 5)',
+        value: 'log(1E5)',
         result: 5,
     },
     {
@@ -87,5 +87,22 @@ module.exports = [
         value: 'sin(30 + cos(30 * tan(60)))',
         result: 0.50928462191,
         isDeg: true
+    },
+    {
+        value: 'sin(30)+cos(45)',
+        result: 1.20710678119,
+        isDeg: true
+    },
+    {
+        value: 'ln(e) + log(1E9)',
+        result: 10,
+    },
+    {
+        value: 'sin(π / 2) / cos(π / 2)',
+        result: 'Error',
+    },
+    {
+        value: '0√(4) / 3',
+        result: 'Infinity',
     }
 ];

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott