An option is to use the Newton-Raphson iterations, known to converge quadratically (so that the number of exact bits will grow like 1, 2, 4, 8, 16, 32, 64).
First compute the inverse of y
with the iterates
z(n+1) = z(n) (2 - z(n) y(n)),
and after convergence form the product
x.z(N) ~ x/y
But the challenge is to find a good starting approximation z(0)
, which should be within a factor 2
of 1/y
.
If the context allows it, you can play directly with the exponent of the floating-point representation and replace Y.2^e
by 1.2^-e
or √2.2^-e
.
If this is forbidden, you can setup a table of all the possible powers of 2 in advance and perform a dichotomic search to locate y
in the table. Then the inverse power is easily found in the table.
For double precision floats, there are 11
exponent bits so that the table of powers should hold 2047
values, which can be considered a lot. You can trade storage for computation by storing only the exponents 2^0
, 2^±1
, 2^±2
, 2^±3
... Then during the dichotomic search, you will recreate the intermediate exponents on demand by means of products (i.e. 2^5 = 2^4.2^1
), and at the same time, form the product of inverses. This can be done efficiently, using lg(p)
multiplies only, where p=|lg(y)|
is the desired power.
Example: lookup of the power for 1000
; the exponents are denoted in binary.
1000 > 2^1b = 2
1000 > 2^10b = 4
1000 > 2^100b = 16
1000 > 2^1000b = 256
1000 < 2^10000b = 65536
Then
1000 < 2^1100b = 16.256 = 4096
1000 < 2^1010b = 4.256 = 1024
1000 > 2^1001b = 2.256 = 512
so that
2^9 < 1000 < 2^10.
Now the Newton-Raphson iterations yield
z0 = 0.001381067932
z1 = 0.001381067932 x (2 - 1000 x 0.001381067932) = 0.000854787231197
z2 = 0.000978913251777
z3 = 0.000999555349049
z4 = 0.000999999802286
z5 = 0.001