Re: Remainder
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
|
Not Categorized, Please Help
|
|