From: Dan Becker <db19606@gm...>  20110108 22:20:51

My reading of the hyperspec leads me to believe that the following should return T for all numbers and divisors: (let ((number 0.036d0) (divisor 0.001d0)) (multiplevaluebind (q r) (truncate number divisor) (= number (+ (* q divisor) r)))) But for this case (truncate .036d0 .001d0), it doesn't. In particular, it gives the remainder as 0d0, but 36*.001d0 is not the same floating point number as 0.036d0. Dan  Dan Becker 
From: Dan Becker <db19606@gm...>  20110108 22:31:20

Sorry, I should have said that this is with clisp 2.49 & 2.44 on ubuntu x8664. On Sat, Jan 8, 2011 at 3:20 PM, Dan Becker <db19606@...> wrote: > My reading of the hyperspec leads me to believe that the following > should return T for all numbers and divisors: > > (let ((number 0.036d0) > (divisor 0.001d0)) > (multiplevaluebind (q r) > (truncate number divisor) > (= number > (+ (* q divisor) r)))) > > But for this case (truncate .036d0 .001d0), it doesn't. In particular, > it gives the remainder as 0d0, but 36*.001d0 is not the same floating > point number as 0.036d0. > > Dan >  > Dan Becker >  Dan Becker 303/4976824 
From: Sam Steingold <sds@gn...>  20110109 17:45:36

> * Dan Becker <qo19606@...> [20110108 15:20:45 0700]: > > My reading of the hyperspec leads me to believe that the following > should return T for all numbers and divisors: > > (let ((number 0.036d0) > (divisor 0.001d0)) > (multiplevaluebind (q r) > (truncate number divisor) > (= number > (+ (* q divisor) r)))) > > But for this case (truncate .036d0 .001d0), it doesn't. In particular, > it gives the remainder as 0d0, but 36*.001d0 is not the same floating > point number as 0.036d0. I don't think this rounding error is relevant. All floating point equalities should always be taken as only meaningful up to the rounding error. E.g., sbcl satisfies you requirements for TRUNCATE, but FLOOR returns a negative remainder for the same arguments.  Sam Steingold (http://sds.podval.org/) on Ubuntu 10.04 (lucid) http://dhimmi.com http://www.PetitionOnline.com/tap12009/ http://www.memritv.org http://thereligionofpeace.com http://ffii.org This message is rot13 encrypted (twice!); reading it violates DMCA. 
From: Dan Becker <db19606@gm...>  20110109 21:40:05

On Sun, Jan 9, 2011 at 10:45 AM, Sam Steingold <sds@...> wrote: >> * Dan Becker <qo19606@...> [20110108 15:20:45 0700]: >> >> My reading of the hyperspec leads me to believe that the following >> should return T for all numbers and divisors: >> >> (let ((number 0.036d0) >> (divisor 0.001d0)) >> (multiplevaluebind (q r) >> (truncate number divisor) >> (= number >> (+ (* q divisor) r)))) >> >> But for this case (truncate .036d0 .001d0), it doesn't. In particular, >> it gives the remainder as 0d0, but 36*.001d0 is not the same floating >> point number as 0.036d0. > > I don't think this rounding error is relevant. > All floating point equalities should always be taken as only meaningful > up to the rounding error. Well, sure, and so maybe when you read the following in the hyperspec: > These functions divide number by divisor, returning a quotient and remainder, such that > > quotient*divisor+remainder=number it's OK to interpret it as meaning "the two sides will be equal within the limits of floatingpoint roundoff errors". On the other hand, you could also interpret it as meaning "you will get an answer that will always satisfy this equality", so my question is whether one interpretation is correct or whether both are OK. > E.g., sbcl satisfies you requirements for TRUNCATE, but FLOOR returns a > negative remainder for the same arguments. Actually, sbcl satisfies my equality for truncate, floor, and round (in all cases returning a negative remainder), but not for ceiling. In fact, sbcl gives 37, not 36, as the quotient when using ceiling: * (ceiling 0.036d0 0.001d0) 37 0.001000000000000007d0 Now that is really surprising! But if it is an issue, it's not an issue for clisp :) Dan  Dan Becker 303/4976824 
From: Sam Steingold <sds@gn...>  20110404 16:42:02

> * Dan Becker <qo19606@...> [20110109 13:54:10 0700]: > > Well, sure, and so maybe when you read the following in the hyperspec: > >> These functions divide number by divisor, returning a quotient and remainder, such that >> >> quotient*divisor+remainder=number > > it's OK to interpret it as meaning "the two sides will be equal within > the limits of floatingpoint roundoff errors". On the other hand, you > could also interpret it as meaning "you will get an answer that will > always satisfy this equality", so my question is whether one > interpretation is correct or whether both are OK. Let me repeat: >> All floating point equalities should always be taken as only >> meaningful up to the rounding error. More precisely: two floats will be equal (as in "bitbybit" or "EQL") only in 3 cases: 1. by "accident": 1.0 + 3.0 = 2.0 + 2.0 2. if they are EQ (i.e., the same object in memory): (let ((x 1.0)) (= x x)) 3. if they have been generated by an identical process from the same inputs: (log 3) = (log 3) (float 22/7) = (float 22/7) E.g., this is correct in any IEEEcompliant system: ( 1.1 0.9) ==> 0.20000005 Moreover, if we were to somehow manage to return 0.2 there, we would have been broken. (http://docs.sun.com/source/8063568/ncg_goldberg.html) Now, back to truncate: you cannot expect the equality you quote to be always correct in the sense of EQL, only up to a rounding error. Even if some implementations do manage to enforce that equality, they will break other conditions instead (e.g., as you observed yourself, negative numbers instead of 0). If you want to have that (and other) invariant always satisfied, you should be using exact numbers (integers and ratios). I am sorry, but that is a fact of life: A number problem "solved" with floats turns into 1.9999999999999998 problems.  Sam Steingold (http://sds.podval.org/) on CentOS release 5.5 (Final) X http://mideasttruth.com http://dhimmi.com http://palestinefacts.org http://memri.org http://www.memritv.org http://camera.org http://truepeace.org Murphy's Law was probably named after the wrong guy. 