Re: Remainder
- Posted by Robert Craig <rds at RapidEuphoria.com> Nov 08, 2003
- 648 views
kbochert at copper.net wrote: > A solution is to observe the bit pattern of the double generated by X/Y > and correct the case where it is a single bit less than a whole number. > > In C: (and without sign stuff) > double rem( double X, double Y) > struct { > double d; > long L[2]; > } z; > z.d = X / Y; > if (L[0] == -1) { > L[0] = 0; > ++L[1]; > } ; > return X - floor (z) * Y > } > > (Basically, if X is a multiple of Y, then the error case division produces > a double whose bit pattern looks something like: > 0x0048FFFFFFFFFFFF ) > > This works very nicely on all cases I have tried where X is a multiple > of Y, and at worst, decreases the accuracy of a very few remainders() > ( 1 in 65k?) by a single bit. > > > How do you do this in EU?? You have my source. In runtime.c, Dremainder(), you can see that I just call the C fmod() function, which I assume executes an Intel instruction. I also have a cryptic comment "for now". I don't remember why I said that. Maybe I thought there was a speed optimization I could do. I never attempt to "fix" problems due to finite floating-point accuracy. Most languages that I'm aware of leave it to the programmer to handle situations like this. One exception is APL, which has a concept called "comparison tolerance" or "fuzz". In APL if two numbers are the same to about 13 digits (as I recall) then APL considers them to be exactly equal. The programmer can adjust this value up or down if he wants. This fuzz value pervades the whole APL system. I believe it also affects operations like floor and remainder, just like your idea above, but the differences can be much more than 1 bit. The fuzz factor idea solves a lot of problems, but you can have weird cases where for example A = B and B = C but A != C I don't think computer science types are happy with the idea. Regards, Rob Craig Rapid Deployment Software http://www.RapidEuphoria.com