Ok. This is second step for optimizing the sqrt.
I developed few days ago and there is the precedent problem of oscillating series of Newton. I have not applicated the solution of penpen and Aacini for the moment.
What is the question that i raise?
When perform a sqrt the integer/integral part is performed by the precedent developed code
Integer 32 BIT SQRT. But for normal application is necessary some time the fractional part.
In the previus developed code I, dbenham and trebor68 have used the classic schoolar algorithm with good result in term of precision and velocity, but I go down for a
very fast solution. In this mode the
32bit of the result can be full of the fractional part.
In this i need your help.
I introduce a my understud of
FIXED POINT mathematic.
For example the SQRT result can be of the type
5.4. 5 integral digit plus 4 fractional digit.
And the result can be stored in TWO variables or in the same variable at BIT/DECIMAL position different.
This is an example of start to compute a sqrt with fractional part using the INTEGER 32bit Sqrt
Code: Select all
@echo off
setlocal EnableDelayedExpansion
Rem Fixed Point
Rem If you have a fractional number, than precalc multiply by EVEN power of 10.
Rem es. SQRT(1.2)=SQRT(1.2*100)/10=SQRT(120)/10
rem define sqrt
set "Sqrt(N)=( x=(N)/(11*1024)+40-^!N*9, x=((N)/x+x)/2, x=((N)/x+x)/2, x=((N)/x+x)/2, x=((N)/x+x)/2, x=((N)/x+x)/2, x/=(1+((N)>>31)))"
rem es. sqrt 25 with 1 decimal
set /A "num=!Sqrt(N):N=25*100!"
echo Sqrt(25.0)=%num:~0,-1%.%num:~-1% & echo(
rem es. sqrt 28.0
set /A "num=!Sqrt(N):N=28*100!"
echo Sqrt(28.0)=%num:~0,-1%.%num:~-1% & echo(
rem es sqrt 2.0000 (with 4 decimal)
set /A "num=!Sqrt(N):N=2*100*100*100*100!"
echo Sqrt(2.0000)=%num:~0,-4%.%num:~-4% & echo(
result:
Code: Select all
Sqrt(25.0)=5.0
Sqrt(28.0)=5.2
Sqrt(2.0000)=1.4142
This is limitated because the 32BIT. And the max number of digit rappresentable is 123.4567890 or 12345678.90 and all other combination. EDIT: (my flame:THIS is not TRUE)
The best method is get the REMAINDER and continue from there.
I have developed in this direction. I get the
integer result of sqrt and the
Remainder
and I have probed to applicate the Newton iteration!
I introduce the simple mathematic (I'm not an expert...)
You can see this example on
StackOverflow But there isn't the Newton implementation. I done
Call the integer sqrt "ISQRT" and "SQRT" is the real/floating point.
ISQRT(140)=11
140=11^2+19 (19 is the REMAINDER = N-ISQRT(N)*ISQRT(N)) [1]
The SQRT(140) = 11,832 that is (11+0.832)
that is (11+0.832)^2=140 [2]
we need found 0.832 and then rewrite the [2]:
(11+x)^2=140
expand this : 11^2+2*11*x+x^2=140
but if we get the [1] we see that 2*11*x+x^2=19
With a guess of 0.5 (0<x<1) iterating via newton we get the fractional part in about
3 iteration.
That is:
Code: Select all
set "Sqrt(N)=( x=(N)/(11*1024)+40-^!N*9, x=((N)/x+x)/2, x=((N)/x+x)/2, x=((N)/x+x)/2, x=((N)/x+x)/2, x=((N)/x+x)/2, Sqrt_Remai_der=(N)-x*x, x=x )"
rem approx via newton
rem es. sqrt of 60000
set /A "num=!Sqrt(N):N=60000!"
echo Sqrt(60000)=%num% Remainder=%Sqrt_Remai_der% & echo(
echo 2*%num%*x+x*x-%Sqrt_Remai_der%=0
rem set /A approx=0.5-(0.25+2*num/2-Sqrt_Remai_der)/(2*0.5+2*num) & rem guess=0.5
rem set /A approx=0.5*1000-(0.25*1000+2*num/2*1000-Sqrt_Remai_der*1000)/(2*0.5+2*num) & rem guess=0.5
set /A approx=500-(250+2*num/2*1000-Sqrt_Remai_der*1000)/(1+2*num)
For /L %%I in (1,1,2) do set /A approx=approx-(approx*approx/1000+2*num*approx-Sqrt_Remai_der*1000)*1/(2*approx/1000+2*num)
echo Sqrt(60000)=%num%.%approx% approx. (244.948...) & echo(
rem es. sqrt of 2
set /A "num=!Sqrt(N):N=2!"
echo Sqrt(2)=%num% Remainder=%Sqrt_Remai_der% & echo(
echo 2*%num%*x+x*x-%Sqrt_Remai_der%=0
set /A approx=500-(250+2*num/2*1000-Sqrt_Remai_der*1000)/(1+2*num)
For /L %%I in (1,1,2) do set /A approx=approx-(approx*approx/1000+2*num*approx-Sqrt_Remai_der*1000)*1/(2*approx/1000+2*num)
echo Sqrt(2)=%num%.%approx% (1.414...) & echo(
rem es. sqrt of 3
set /A "num=!Sqrt(N):N=3!"
echo Sqrt(3)=%num% Remainder=%Sqrt_Remai_der% & echo(
echo 2*%num%*x+x*x-%Sqrt_Remai_der%=0
set /A approx=500-(250+2*num/2*1000-Sqrt_Remai_der*1000)/(1+2*num)
For /L %%I in (1,1,2) do set /A approx=approx-(approx*approx/1000+2*num*approx-Sqrt_Remai_der*1000)*1/(2*approx/1000+2*num)
echo Sqrt(3)=%num%.%approx% (1.732...) & echo(
rem es. sqrt of 2147483647
set /A "num=!Sqrt(N):N=2147483647!"
echo Sqrt(2147483647)=%num% Remainder=%Sqrt_Remai_der% & echo(
echo 2*%num%*x+x*x-%Sqrt_Remai_der%=0
set /A approx=500-(250+2*num/2*1000-Sqrt_Remai_der*1000)/(1+2*num)
For /L %%I in (1,1,2) do set /A approx=approx-(approx*approx/1000+2*num*approx-Sqrt_Remai_der*1000)*1/(2*approx/1000+2*num)
echo Sqrt(2147483647)=%num%.%approx% (46340.950...) & echo(
rem es. sqrt of 65535
set /A "num=!Sqrt(N):N=65535!"
echo Sqrt(65535)=%num% Remainder=%Sqrt_Remai_der% & echo(
echo 2*%num%*x+x*x-%Sqrt_Remai_der%=0
set /A approx=500-(250+2*num/2*1000-Sqrt_Remai_der*1000)/(1+2*num)
For /L %%I in (1,1,2) do set /A approx=approx-(approx*approx/1000+2*num*approx-Sqrt_Remai_der*1000)*1/(2*approx/1000+2*num)
echo Sqrt(65535)=%num%.%approx% (255.998...) & echo(
Rem Patching
And we get the error at 65535 with the
REMAINDER=-1Code: Select all
Sqrt(2)=1 Remainder=1
2*1*x+x*x-1=0
Sqrt(2)=1.414 (1.414...)
Sqrt(3)=1 Remainder=2
2*1*x+x*x-2=0
Sqrt(3)=1.732 (1.732...)
Sqrt(2147483647)=46340 Remainder=88047
2*46340*x+x*x-88047=0
Sqrt(2147483647)=46340.950 (46340.950...)
Sqrt(65535)=256 Remainder=-1
2*256*x+x*x--1=0
Sqrt(65535)=256.-1 (255.998...)
I have not patched at the moment. I need a confirm by you if the error is the same
@penpen
I can't understund how to patch the ! problem in the percent expansion... I will go down the iteration from 5 to 4 or 3
EDIT: added the definition of ISQRT with remainder. Not optimized.
EDIT2: correct explain on ISQRT(140)
Einstein1969