Преглед изворни кода

Merge pull request #5374 from jonasdiemer/calc-pretty-floats

Calculator: improved output of float numbers
Tienson Qin пре 3 година
родитељ
комит
3c886f4330
4 измењених фајлова са 39 додато и 24 уклоњено
  1. 1 0
      package.json
  2. 23 19
      src/main/frontend/extensions/calc.cljc
  3. 10 5
      src/test/frontend/extensions/calc_test.cljc
  4. 5 0
      yarn.lock

+ 1 - 0
package.json

@@ -85,6 +85,7 @@
         "@sentry/tracing": "^6.18.2",
         "@tabler/icons": "1.54.0",
         "@tippyjs/react": "4.2.5",
+        "bignumber.js": "^9.0.2",
         "capacitor-voice-recorder": "2.1.0",
         "chokidar": "3.5.1",
         "chrono-node": "2.2.4",

+ 23 - 19
src/main/frontend/extensions/calc.cljc

@@ -3,6 +3,9 @@
   (:require [clojure.edn :as edn]
             [clojure.string :as str]
             [frontend.util :as util]
+
+            [bignumber.js :as bn]
+
             #?(:clj [clojure.java.io :as io])
             #?(:cljs [shadow.resource :as rc])
             #?(:cljs [rum.core :as rum])
@@ -24,35 +27,36 @@
 
 (defn new-env [] (atom {}))
 
+;; TODO: Set DECIMAL_PLACES https://mikemcl.github.io/bignumber.js/#decimal-places
+
 (defn eval* [env ast]
   (insta/transform
-   {:number     (comp edn/read-string #(str/replace % "," ""))
-    :percent    (fn percent [a] (/ a 100.00))
-    :scientific edn/read-string
-    :negterm    (fn neg [a] (- a))
+   {:number     (comp bn/BigNumber #(str/replace % "," ""))
+    :percent    (fn percent [a] (-> a (.dividedBy 100.00)))
+    :scientific (comp bn/BigNumber edn/read-string)
+    :negterm    (fn neg [a] (-> a (.negated)))
     :expr       identity
-    :add        +
-    :sub        -
-    :mul        *
-    :div        /
-    :pow        (fn pow [a b]
-                  #?(:clj (java.lang.Math/pow a b) :cljs (js/Math.pow a b)))
+    :add        (fn add [a b] (-> a (.plus b)))
+    :sub        (fn sub [a b] (-> a (.minus b)))
+    :mul        (fn mul [a b] (-> a (.multipliedBy b)))
+    :div        (fn div [a b] (-> a (.dividedBy b)))
+    :pow        (fn pow [a b] (-> a (.exponentiatedBy b)))
     :log        (fn log [a]
-                  #?(:clj (java.lang.Math/log10 a) :cljs (js/Math.log10 a)))
+                  #?(:clj (java.lang.Math/log10 a) :cljs (bn/BigNumber (js/Math.log10 a))))
     :ln         (fn ln [a]
-                  #?(:clj (java.lang.Math/log a) :cljs (js/Math.log a)))
+                  #?(:clj (java.lang.Math/log a) :cljs (bn/BigNumber (js/Math.log a))))
     :sin        (fn sin [a]
-                  #?(:clj (java.lang.Math/sin a) :cljs (js/Math.sin a)))
+                  #?(:clj (java.lang.Math/sin a) :cljs (bn/BigNumber(js/Math.sin a))))
     :cos        (fn cos [a]
-                  #?(:clj (java.lang.Math/cos a) :cljs (js/Math.cos a)))
+                  #?(:clj (java.lang.Math/cos a) :cljs (bn/BigNumber(js/Math.cos a))))
     :tan        (fn tan [a]
-                  #?(:clj (java.lang.Math/tan a) :cljs (js/Math.tan a)))
+                  #?(:clj (java.lang.Math/tan a) :cljs (bn/BigNumber(js/Math.tan a))))
     :atan       (fn atan [a]
-                  #?(:clj (java.lang.Math/atan a) :cljs (js/Math.atan a)))
+                  #?(:clj (java.lang.Math/atan a) :cljs (bn/BigNumber(js/Math.atan a))))
     :asin       (fn asin [a]
-                  #?(:clj (java.lang.Math/asin a) :cljs (js/Math.asin a)))
+                  #?(:clj (java.lang.Math/asin a) :cljs (bn/BigNumber(js/Math.asin a))))
     :acos       (fn acos [a]
-                  #?(:clj (java.lang.Math/acos a) :cljs (js/Math.acos a)))
+                  #?(:clj (java.lang.Math/acos a) :cljs (bn/BigNumber(js/Math.acos a))))
     :assignment (fn assign! [var val]
                   (swap! env assoc var val)
                   val)
@@ -101,4 +105,4 @@
            [:span (cond
                     (nil? line)           ""
                     (failure? line) "?"
-                    :else                 line)]])])))
+                    :else                 (str line))]])])))

+ 10 - 5
src/test/frontend/extensions/calc_test.cljc

@@ -1,10 +1,15 @@
 (ns frontend.extensions.calc-test
   (:require [clojure.test :as test :refer [are deftest testing]]
+            [clojure.edn :as edn]
             [frontend.extensions.calc :as calc]))
 
+(defn convert-bigNum [b]
+  (edn/read-string (str b))
+  )
+
 (defn run [expr]
   {:pre [(string? expr)]}
-  (calc/eval (calc/parse expr)))
+  (convert-bigNum (calc/eval (calc/parse expr))))
 
 (deftest basic-arithmetic
   (testing "numbers are parsed as expected"
@@ -102,7 +107,7 @@
   (testing "variables can be remembered"
     (are [final-env expr] (let [env (calc/new-env)]
                             (calc/eval env (calc/parse expr))
-                            (= final-env @env))
+                            (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
       {"a" 1}        "a = 1"
       {"a" -1}        "a = -1"
       {"variable" 1} "variable = 1 + 0 * 2"
@@ -114,7 +119,7 @@
   (testing "variables can have underscores"
     (are [final-env expr] (let [env (calc/new-env)]
                             (calc/eval env (calc/parse expr))
-                            (= final-env @env))
+                            (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
       {"a_a" 1}         "a_a = 1"
       {"x_yy_zzz" 1}    "x_yy_zzz= 1"
       {"foo_bar_baz" 1} "foo_bar_baz = 1 + -0 * 2"))
@@ -122,7 +127,7 @@
     (are [final-env exprs] (let [env (calc/new-env)]
                              (doseq [expr exprs]
                                (calc/eval env (calc/parse expr)))
-                             (= final-env @env))
+                            (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
       {"a" 1 "b" 2}          ["a = 1" "b = a + 1"]
       {"a" 1 "b" 0}          ["a = 1" "b = -a + 1"]
       {"a" 1 "b" 3}          ["a = 1" "b=a*2+1"]
@@ -133,7 +138,7 @@
     (are [final-env exprs] (let [env (calc/new-env)]
                              (doseq [expr exprs]
                                (calc/eval env (calc/parse expr)))
-                             (= final-env @env))
+                            (= final-env (into {} (for [[k v] @env] [k (convert-bigNum v)]))))
       {"a" 2}              ["a = 1" "a = 2"]
       {"a" 2 "b" 2}        ["a = 1" "b = a + 1" "a = b"]
       {"variable" 1 "x" 0} ["variable = 1 + 0 * 2" "x = log(variable)" "x = variable - 1"])))

+ 5 - 0
yarn.lock

@@ -1655,6 +1655,11 @@ [email protected]:
   resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
   integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==
 
+bignumber.js@^9.0.2:
+  version "9.0.2"
+  resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.2.tgz#71c6c6bed38de64e24a65ebe16cfcf23ae693673"
+  integrity sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==
+
 binary-extensions@^1.0.0:
   version "1.13.1"
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"