Parsing 在ClojureScript程序中使用Cuerdas解析十进制数

Parsing 在ClojureScript程序中使用Cuerdas解析十进制数,parsing,floating-point,numbers,decimal,clojurescript,Parsing,Floating Point,Numbers,Decimal,Clojurescript,我正在使用一个 ClojureScript程序解析浮点数。有时,来自 用户缺少完整的部分,如0.1的.1。我需要处理这件事。 但我在比较解析的数字时遇到了奇怪的结果: (= 0.1 (parse-number "0.1")) ;; => true (= .1 (parse-number "0.1")) ;; => true (= 0.1 (parse-number ".1")) ;; => false (= .1

我正在使用一个 ClojureScript程序解析浮点数。有时,来自 用户缺少完整的部分,如
0.1
.1
。我需要处理这件事。 但我在比较解析的数字时遇到了奇怪的结果:

(= 0.1 (parse-number "0.1"))
;; => true

(= .1 (parse-number "0.1"))
;; => true

(= 0.1 (parse-number ".1"))
;; => false

(= .1 (parse-number ".1"))
;; => false
上面最后两个结果令我惊讶。当比较字面值I时 获得预期结果:

(= 0 .0)
;; => true
当我只解析没有整数的十进制数时,这种奇怪的行为也是可见的 第二部分,如下所示:

(parse-number ".1")
;; => .1

.1
;; => 0.1
我发现我可以使用
js/parseFloat
得到我想要的东西,但我很好奇 使用Cuerdas时出现这种行为的原因是什么?这个
.1
值是什么 它与
0.1
有何不同?

源代码如下:

(defn解析号
“用于解析数字的通用函数,如
字符串到数字。它同时适用于两个整数
和浮动。”
[s]
(如无)
#(:cljs js/NaN:clj Double/NaN)
(如果(数字?s)
(edn/读取字符串s)
#(:cljs js/NaN:clj Double/NaN)))
“.1”
“0.1”
都被认为是(通过正则表达式检查在cuerdas中实现):

cljs.user=>(定义为“^[+-]?([0-9]*\.?[0-9]+[0-9]+\.?[0-9]+\)([eE][+-]?[0-9]+)?$”)
#'cljs.user/re
user=>(布尔值(重新匹配“0.1”))
真的
cljs.user=>(布尔值(重匹配重“.1”))
真的
因此,他们将被阅读

读取字符串
“0.1”
时,返回类型为
js/Number
,但
“.1”
类型为
cljs.core/Symbol

cljs.user=>(cljs.reader/read-string.1)
1.
cljs.user=>(cljs.reader/read-string“0.1”)
0.1
cljs.user=>(类型(cljs.reader/read-string“0.1”))
#对象[编号]
cljs.user=>(类型(cljs.reader/read-string“.1”))
cljs.core/Symbol
因此,尽管它看起来正确地解析了.1,但实际上它将其转换为一个符号。符号
.1
不等于数字
.1

请注意,
parse number
属于cuerdas,因为它“是一个字符串操作库,而不是一个数字解析库”。

我有一些适用于CLJ和CLJS的库。从单元测试中,我们得到了

标题:

(ns tst.tupelo.parse
  ;---------------------------------------------------------------------------------------------------
  ;   https://code.thheller.com/blog/shadow-cljs/2019/10/12/clojurescript-macros.html
  ;   http://blog.fikesfarm.com/posts/2015-12-18-clojurescript-macro-tower-and-loop.html
  #?(:cljs (:require-macros
             [tupelo.misc]
             [tupelo.testy]))
  (:require
    [clojure.test] ; sometimes this is required - not sure why
    [tupelo.parse :as tpar]
    [tupelo.misc :as misc]
    [tupelo.core :as t :refer [spy spyx spyxx spyx-pretty]]
    [tupelo.testy :refer [deftest testing is dotest isnt is= isnt= is-set= is-nonblank=
                          throws? throws-not? define-fixture]])
  #?(:clj (:import [java.lang Math]))
  )
解析整数:

#?(:cljs
   (do
     (dotest
       (is= 0 (tpar/parse-int "0"))
       (is= 15 (tpar/parse-int "15"))
       (is= -5 (tpar/parse-int "-5"))
       (is= 99999 (tpar/parse-int "99999"))

       (throws? (tpar/parse-int ""))
       (throws? (tpar/parse-int "05"))
       (throws? (tpar/parse-int "123xxx"))
       (throws? (tpar/parse-int "12x3"))
       (throws? (tpar/parse-int "12.3"))
       (throws? (tpar/parse-int "xxx123")))
分析浮动

     (dotest
       (is= 0 (tpar/parse-float "0"))
       (is= 0 (tpar/parse-float "0.0"))
       (is= 12.345 (tpar/parse-float "12.345"))
       (is= -5.1 (tpar/parse-float "-5.1"))
       (is= 42 (tpar/parse-float "42.0"))
       (is= 42 (tpar/parse-float "42"))
       (is= 123.45 (tpar/parse-float "1.2345e2"))

       (throws? (tpar/parse-float ""))
       (throws? (tpar/parse-float "xxx1.23"))
       (throws? (tpar/parse-float "1.23xxx"))
       (throws? (tpar/parse-float "1.2xx34")))
     ))

谢谢,我会试试的。