在我的学习期间,我发现了这个:
;Clojure 1.4.0
(def neg_inf -1E-400)
(cond
(= neg_inf 0) "Zero"
(< neg_inf 0) "Negative"
(> neg_inf 0) "Positive"
:default "Neither"
)
;#'user/neg_inf
;user=> "Neither"
Run Code Online (Sandbox Code Playgroud)
这是一个错误吗?
然后,我试过:
(Math/signum -1E-400) ;-0.0
Run Code Online (Sandbox Code Playgroud)
这是我发现在某个数字被认为是-0.0时发现的一种方式:
(Math/copySign 1. -0.) ;-1.0
(Math/copySign 1. -1E-99999999999999999999999);-1.0
Run Code Online (Sandbox Code Playgroud)
通过这种方式,我可以知道一个数字是否为负数,即使它非常接近于零.
所有这一切都是因为我试图解决这个问题:
(defn hexadecimal-to-degrees [rah ram ras]
{ :pre [ (>= rah 0) (< rah 24) (>= ram 0) (< ram 60) (>= ras 0) (< ras 60) ]
:post [ (>= % 0) ]
}
(/ (+ rah (/ ram 60) (/ ras 3600)) 15)
)
(hexadecimal-to-degrees -1E-400 -1E-400 -1E-400)
;-0.0 ; OMG, no Assert failed here!
Run Code Online (Sandbox Code Playgroud)
由于右上升(地球经度的天体等值)没有负值,我正在测试后置条件是否以确保函数不会为RA返回负值的方式工作,无论我传递给的是什么数字功能..
我怀疑在引擎盖下(= 0 -1E-400)使用java的Double.equals()方法,它将正面和负面的零视为不相等.此行为违反了IEEE浮点标准.其他比较运算符转换为符合标准的其他方法,即将+0.0和-0.0视为相等.
要获得符合标准的行为,请使用数字等效运算符==.因此,(== 0 -0.0)评估为true.
有关维基百科上签名和未签名零的更多信息:http://en.wikipedia.org/wiki/Signed_zero
更一般地说:比较浮点数是否相等应该总是引起怀疑.