"truncated to their floor value" ?!

Started by Leibnix, March 05, 2010, 06:50:19 PM

Previous topic - Next topic

Leibnix

Hi!



The newlisp manual says:
QuoteFloating point values in arguments to +, -, *, /, and % are truncated to their floor value.

Since for instance the floor of -1.1 is -2 I would take this to mean (+ -1.1 -2.2) should equal -5, not -3.  



Is it just me or is this a bug or a typo in the manual?

johu

#1
I think that newLISP works the following :


QuoteFloating point values in arguments to +, -, *, /, and % are truncated to their integer part.


What do you think?

Leibnix

#2
I concur. But truncating to the integer part (or rounding towards zero) is a very funny thing to do in a mathematical sense. For instance, It means if you plot the function, you see an irregular section of the plot around zero. This irregularity can be the source of strange bugs if you are not constantly aware of it. People has been complaining about this 'feature' in standard c truncation for decedas.



But my main point is that the manual claims newlisp 'floors' the values. 'Floor' has a definite meaning in many math and computer science texts. It means to round down towards negative infinity.



Or doesn't it?



Btw, hope I don't sound too sour. I just read about newlisp in a Linux magazine and decided to give it a try. I REALLY like the slicing and indexing facilities! ^_^ I also am attracted to the heavy use of value assignment, because the first language I learned ("Euphoria") worked similarly. In that lingo there was no such thing as a reference!

Lutz

#3
The description in the upcoming version 10.2.0 manual is changed now to:  "... are truncated to the integer value closest to 0":



http://www.newlisp.org/downloads/development/latest/newlisp_manual.html">http://www.newlisp.org/downloads/develo ... anual.html">http://www.newlisp.org/downloads/development/latest/newlisp_manual.html



Welcome to newLISP.

cormullion

#4
btw - there's a floor function.


> (floor -8.5)
-9


which does what you expect. Also, note that:


> (integer? (floor -8.5))
nil


There's a bit more about newLISP arithmetic at http://en.wikibooks.org/wiki/Introduction_to_newLISP/Working_with_numbers">//http://en.wikibooks.org/wiki/Introduction_to_newLISP/Working_with_numbers. It would be great if you could find or even fix any errors I've made there! :)

Lutz

#5
Thanks Cormullion ... and for the floating point experts thee is also the file qa-float in the source distribution. Here included in its entirety:


#!/usr/bin/newlisp

; Test IEE compliance of some FP operations and handling of 'inf' and 'NaN'
; numbers. In all versions of newLISP (32Bit and 64Bit) floating point numbers
; are represented as IEE 754 64-bit: Double (binary64) numbers.

; Thanks to Nelson H.F. Beebe <beebe@math.utah.edu> for some of the tests
; in this file

(println)
(println "Testing floating point performance")

(set 'aNan (sqrt -1))
(set 'aInf (div 1.0 0))
(set 'aNegInf (div -1 0))

; operation on NaN result in NaN

(set 'tests '(
"operation on NaN result in NaN"
(NaN? (mul 1.0 aNan))
(NaN? (div 1.0 aNan))
(NaN? (add 1.0 aNan))
(NaN? (sub 1.0 aNan))
(NaN? (sin aNan))
(NaN? (cos aNan))
(NaN? (tan aNan))
(NaN? (atan aNan))
"comparison with NaN is always nil"
(not (< 1.0 aNan))
(not (> 1.0 aNan))
(not (>= 1.0 aNan))
(not (<= 1.0 aNan))
(not (= aNan aNan))
"NaN is not equal to itself"
(not (= aNan aNan))
"integer operations assume NaN as 0"
(= (- 1 aNan) 1)
(= (+ 1 aNan) 1)
(= (* 1 aNan) 0)
(not (catch (/ 1 aNan) 'error))
(= (>> aNan) 0)
(= (<< aNan) 0)
"integer operations assume inf as max-int"
(= (* 1 aInf) 9223372036854775807)
(= (- aInf 1) 9223372036854775806)
(= (+ aInf 1) -9223372036854775808) ; wrap around
"FP division by inf results in 0"
(= (/ 1 aInf) 0)
(= (div 1 aInf) 0)
"inf specials"
(= aInf aInf)
(NaN? (sub aInf aInf))
"retain sign of -0.0"
(= (set 'tiny (div -1 aInf)) -0.0)
(= (sqrt tiny) -0.0)
"inf is signed too"
(= aNegInf (div -1 0))
(!= aNegInf (div 1 0))
"mod with 0 divisor is NaN"
(NaN? (mod 10 0))
"% with 0 divisor throws error"
(not (catch (% 10 0) 'error))
)
)


(dolist (t tests)
(if (string? t)
(println (format "n%-47sn%s" t (dup "-" 47)))
(let (result (eval t))
(println (format "%40s => %s" (string t) (string result)))
(push result result-list))
)
)

(println)

(set 'result '())
(set 'u 1.0)
(while (> u 0.0) (set 'u (mul u 0.5)) (push u result))
(println "support of subnormals: " (0 2 result) " => (0 4.940656458e-324)")


(set 'result '())
(set 'u 1.0)
(while (!= 1.0 (add 1.0 u)) (set 'u (mul u 0.5)) (push u result))
(println "machine epsilon: " (result 0) " => 1.110223025e-16")

(println)
(if-not (apply and result-list)
(println ">>>>> PROBLEM in floating point tests")
(println ">>>>> floating point tests SUCCESSFUL")
)

(exit)

johu

#6
Thank you for the response, Leibnix.

I think that your opinion is right.

Then, the manual is corrected. (Thank you, Lutz.)



And, I had used C before.

I often used to convert integer form float by the following :
(printf "%dn" (int)(-2.3)) → -2
Then, I think that the following is usual in newLISP :
> (int -2.3)
-2
>

Also, integer operations works.

Leibnix

#7
I just want to say it's nice to see such a friendly and responsive forum. I will have to read and experiment a lot with newlisp before I can hope to be of any help to other beginners.