Author: Dieter Buerssner
Date: 15:38:12 09/16/03
Go up one level in this thread
On September 16, 2003 at 17:48:32, Gerd Isenberg wrote:
Hi Gerd,
only a comment to the later part.
>void findGoodReciprocalConstants()
>{
> double errorMargin = 0.0000001; // !? 0 is also fine here with double
Yes. At least until the result of the devision will be rather small, 0.0 will
work equally well.
> double c = 0x100000000;
> c = c * c - 1.0; // 2**64-1
Note, that this number is no exact double precision floating point number. You
will end up with 2**64. It is an exact extended precision floating point number
on x86 (80 bits with 64 bit mantissa. GNU-C uses this as type long double).
> for (int i = 1; i < 0x10000; i += 2)
> {
> double fdiv = (c + i)/i;
The smallest result, you can get here is around 2**48. This leaves 5 more bits
of precision in type double. So all the results will have a smallest fraction of
2**-5. So you will never get numbers like integer-part.001. You can get
integer-part.00000 or integer-part.03125. At least when I did not do an off by
one error. Even if you make it 2**-6 or 2**-7, 0.0 in the error margin is the
same, as 0.0000001.
> unsigned __int64 idiv = fdiv;
> double rdiv = (double)idiv;
> if ( fdiv >= rdiv - errorMargin && fdiv <= rdiv + errorMargin)
Actually, with a decent compiler and good floating point implementation, you
could use
if (rdiv == fdiv)
here. This is one advantage of well defined IEEE floating point arithmetics.
> printf("0x%08x%08x for mod(%5d)\n", (int)(idiv>>32), (int)idiv, i);
> }
>}
>
>For division/modulos by odd 64-bit constant less than 4096 a correction
>is not necessary.
OTOH, I don't understand this conclusion. I think, you have missed, that double
precision floating point math is not exact enough here.
Cheers,
Dieter
This page took 0.01 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.