Re: Rob's going to hate me... (Remainder bug)
- Posted by kbochert at copper.net Nov 07, 2003
- 630 views
On 7 Nov 2003 at 1:30, Robert Craig wrote: > > > Urzumph wrote: > > Heh, twice in a week, lol > > ? remainder(100,0.01) > > gives 0.01 and I am sure that's not supposed to happen > > This is reproducable with all numbers <= 0.2 > > for some reason, all numbers > .2 work as they should. > > Also, this only affects numbers which are cleanly divisable. > > ? remainder(100.001,0.01) returns 0.001 as it should > > Don't lol too hard. > Your first one wasn't a bug, and neither is this one. > > This remainder issue came up on the mailing list > a few years ago. It's basically an incarnation of the old > "0.1 (0.01 etc.) can't be represented exactly on > Intel hardware" problem. Once or twice every year > someone on this list is shocked to find that > floating-point calculations aren't perfectly exact, > and the error can sometimes be magnified into an > obviously incorrect answer... > > > http://www.listfilter.com/cgi-bin/esearch.exu?fromMonth=2&fromYear=5&toMonth=2&toYear=5&postedBy=rds&keywords=remainder > > (the URL might wrap - be careful) > > Regards, > Rob Craig > Rapid Deployment Software > http://www.RapidEuphoria.com > >From a number of sources: "The fmod() function returns the value x - i * y, for some integer i, such that, if y is non-zero, the result has the same sign as x and magnitude less than the magnitude of y. in Dremainder(): double x, y; if (b->dbl < 1) { // fmod() seems to sometimes goof this! x = a->dbl < 0? -a->dbl: a->dbl; y = b->dbl < 0? -b->dbl: b->dbl; x = x - floor(x / y) * y; if (a->dbl < 0) // sign matches a return (object)NewDouble(-x); return (object)NewDouble(x); } Works for the (100, .01) case (and others I have tried). This leads me to believe that it is a bug in the implementation of fmod() (In Intel's hardware?). Maybe remainders of fractional divisors are seldom done?? Can also be done in Eu code, of course. Ktb Note that the above code is invoked for both fractional and negative divisors -- both work fine.