Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Negative small numbers in Clojure

Tags:

clojure

During my clojure studies, I found this:

;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"

Is it a bug?

Then, I tried:

(Math/signum -1E-400) ;-0.0

Here's a way I found to discover when some number is considered as -0.0 :

(Math/copySign 1. -0.) ;-1.0
(Math/copySign 1. -1E-99999999999999999999999);-1.0

This way, I can know if a number is negative even if it is ridiculously close to zero.

All of this because I were trying to solve this problem:

(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!

Since there is no negative value for Right Ascension (the celestial equivalent of terrestrial longitude), I was testing if the post condition works in a way that guarantees the function will not return a negative value for the RA no matter what numbers I pass to the function..

like image 760
Bruno Alessi Avatar asked Sep 18 '12 11:09

Bruno Alessi


People also ask

How do I make negative numbers in Isdigit?

4- To check negative numbers or decimal numbers using Python isdigit() method, you need to remove the minus or a decimal character before checking. Using lstrip() method you can remove the specified leading characters (used to remove '-' sign here).

Does Isdigit include negative numbers?

isdigit when you want to verify that each and every character in a string is a single digit, that is, not punctuation, not a letter, and not negative.

How do you validate negative numbers in Python?

Python Code:n = float(input("Input a number: ")) if n >= 0: if n == 0: print("It is Zero! ") else: print("Number is Positive number. ") else: print("Number is Negative number.

How negative number is represented in Python?

Negative numbers are written with a leading one instead of a leading zero. So if you are using only 8 bits for your twos-complement numbers, then you treat patterns from "00000000" to "01111111" as the whole numbers from 0 to 127, and reserve "1xxxxxxx" for writing negative numbers.


2 Answers

I suspect that the (= 0 -1E-400) uses java's Double.equals() method under the hood, which treats the positive and negative zeros as unequal. This behavior is a violation of the IEEE floating point standard. The other comparison operators translate to other methods which behave according to the standard, i.e. treat +0.0 and -0.0 as equal.

To get the standard-compliant behavior, use the number-equivalence operator ==. Thus, (== 0 -0.0) evaluates to true.

More about signed and unsigned zero on Wikipedia: http://en.wikipedia.org/wiki/Signed_zero

On a more general note: comparing floating point numbers for equality should always raise suspicions.

like image 149
Rafał Dowgird Avatar answered Sep 20 '22 15:09

Rafał Dowgird


Keep in mind that the behavior of Doubles implies a performance compromise between processor time and accuracy. Clojure makes it easy to work with BigDecimals, which are computationally more expensive but have better accuracy guarantees. You can specify BigDecimal numeric literals by appending 'M' after the literal number, and all numeric operators accept BigDecimals. Quick test drive relevant to your example:

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
like image 29
animal Avatar answered Sep 22 '22 15:09

animal