在 ClojureScript 程序中使用 Cuerdas 解析十进制数
Parse decimal number using Cuerdas in a ClojureScript program
我正在使用 Cuerdas library
解析浮点数的 ClojureScript 程序。有时输入来自
用户缺少组成部分,例如 .1
对应 0.1
。我需要处理这个。
但是当比较解析的数字时,我 运行 进入 st运行ge 结果:
(= 0.1 (parse-number "0.1"))
;; => true
(= .1 (parse-number "0.1"))
;; => true
(= 0.1 (parse-number ".1"))
;; => false
(= .1 (parse-number ".1"))
;; => false
上面最后两个结果让我很惊讶。比较文字数字时我
得到预期的结果:
(= 0 .0)
;; => true
当我只解析没有整数的十进制数时,st运行ge 行为也可见
部分,如下所示:
(parse-number ".1")
;; => .1
.1
;; => 0.1
我发现我可以使用 js/parseFloat
得到我想要的东西,但我很好奇
使用 Cuerdas 时出现这种行为的原因是什么?这个 .1
值是多少
它与 0.1
有何不同?
parse-number
来源如下所示:
(defn parse-number
"General purpose function for parse number like
string to number. It works with both integers
and floats."
[s]
(if (nil? s)
#?(:cljs js/NaN :clj Double/NaN)
(if (numeric? s)
(edn/read-string s)
#?(:cljs js/NaN :clj Double/NaN))))
".1"
和 "0.1"
都被认为是 numeric?
(通过正则表达式检查在 cuerdas 中实现):
cljs.user=> (def re #"^[+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)([eE][+-]?[0-9]+)?$")
#'cljs.user/re
cljs.user=> (boolean (re-matches re "0.1"))
true
cljs.user=> (boolean (re-matches re ".1"))
true
所以它们将被 cljs.reader/read-string
阅读。
读取字符串 "0.1"
时,return 类型是 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=> (type (cljs.reader/read-string "0.1"))
#object[Number]
cljs.user=> (type (cljs.reader/read-string ".1"))
cljs.core/Symbol
因此,虽然它看起来正确地解析了 .1,但实际上它把它变成了一个符号。符号 .1
不等于数字 .1
.
请注意,parse-number
是 cuerdas 的 no longer available in newer versions,因为它“是一个字符串处理库,而不是数字解析库”。
我有一些 numeric parsing functions 适用于 CLJ 和 CLJS。从单元测试中,我们有
headers:
(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")))
))
我正在使用 Cuerdas library
解析浮点数的 ClojureScript 程序。有时输入来自
用户缺少组成部分,例如 .1
对应 0.1
。我需要处理这个。
但是当比较解析的数字时,我 运行 进入 st运行ge 结果:
(= 0.1 (parse-number "0.1"))
;; => true
(= .1 (parse-number "0.1"))
;; => true
(= 0.1 (parse-number ".1"))
;; => false
(= .1 (parse-number ".1"))
;; => false
上面最后两个结果让我很惊讶。比较文字数字时我 得到预期的结果:
(= 0 .0)
;; => true
当我只解析没有整数的十进制数时,st运行ge 行为也可见 部分,如下所示:
(parse-number ".1")
;; => .1
.1
;; => 0.1
我发现我可以使用 js/parseFloat
得到我想要的东西,但我很好奇
使用 Cuerdas 时出现这种行为的原因是什么?这个 .1
值是多少
它与 0.1
有何不同?
parse-number
来源如下所示:
(defn parse-number
"General purpose function for parse number like
string to number. It works with both integers
and floats."
[s]
(if (nil? s)
#?(:cljs js/NaN :clj Double/NaN)
(if (numeric? s)
(edn/read-string s)
#?(:cljs js/NaN :clj Double/NaN))))
".1"
和 "0.1"
都被认为是 numeric?
(通过正则表达式检查在 cuerdas 中实现):
cljs.user=> (def re #"^[+-]?([0-9]*\.?[0-9]+|[0-9]+\.?[0-9]*)([eE][+-]?[0-9]+)?$")
#'cljs.user/re
cljs.user=> (boolean (re-matches re "0.1"))
true
cljs.user=> (boolean (re-matches re ".1"))
true
所以它们将被 cljs.reader/read-string
阅读。
读取字符串 "0.1"
时,return 类型是 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=> (type (cljs.reader/read-string "0.1"))
#object[Number]
cljs.user=> (type (cljs.reader/read-string ".1"))
cljs.core/Symbol
因此,虽然它看起来正确地解析了 .1,但实际上它把它变成了一个符号。符号 .1
不等于数字 .1
.
请注意,parse-number
是 cuerdas 的 no longer available in newer versions,因为它“是一个字符串处理库,而不是数字解析库”。
我有一些 numeric parsing functions 适用于 CLJ 和 CLJS。从单元测试中,我们有
headers:
(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")))
))