在我的学习期间,我发现了这个:
;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"
这是一个错误吗?
然后,我试过了:
(Math/signum -1E-400) ;-0.0
这是我发现在某个数字被认为是-0.0时发现的方式:
(Math/copySign 1. -0.) ;-1.0
(Math/copySign 1. -1E-99999999999999999999999);-1.0
通过这种方式,我可以知道一个数字是否为负数,即使它是非常接近于零。
所有这一切都是因为我试图解决这个问题:
(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!
由于右升天(地球经度的天体等值)没有负值,我正在测试后置条件是否以某种方式工作 保证函数不会为RA返回负值,无论如何 数字我传递给函数..
答案 0 :(得分:8)
我怀疑(= 0 -1E-400)
使用了java的Double.equals()
方法,它将正面和负面的零视为不相等。此行为违反了IEEE浮点标准。其他比较运算符转换为符合标准的其他方法,即将+0.0和-0.0视为相等。
要获得符合标准的行为,请使用数字等效运算符==
。因此,(== 0 -0.0)
评估为true
。
有关维基百科上签名和无符号零的更多信息:http://en.wikipedia.org/wiki/Signed_zero
更一般地说:比较浮点数是否相等应该总是引起怀疑。
答案 1 :(得分:2)
请记住,Doubles的行为意味着处理器时间和准确性之间的性能折衷。 Clojure使得BigDecimals易于使用,BigDecimals计算成本更高但具有更好的准确性保证。您可以通过在文字编号后附加'M'来指定BigDecimal数字文字,并且所有数字运算符都接受BigDecimals。与您的示例相关的快速试驾:
user> (type -1E-400)
java.lang.Double
user> (type -1E-400M)
java.lang.BigDecimal
user> (= 0M -1E-400M)
false
user> (<= 0M -1E-400M)
false
user> (< 0M -1E-400M)
false
user> (>= 0M -1E-400M)
true