====== Quadratwurzel ziehen ======
Das Quadratwurzel zu ziehen ist ein Standard-Problem. 
Es gibt verschiedene Verfahren dafür.
===== signed integer square root (Heron) =====
Hierbei wird mit dem Ausdruck
x' = {{n\over x} + x\over 2}
also Näherungswert=(Schätzwert+Eingangswert/Schätzwert)/2 so lange an das Ergebnis angenähert, bis eine vorher festgelegte Genauigkeit erreicht worden ist. Das Verfahren konvergiert rasch. Algebraisch formuliert lautet die Vorschrift:
  xn+1 = ( xn + a/xn ) / 2
==== Beispiel ====
  a=25, x0=a ; Integer rechnen.
  x1 = (25+25/25)/2 = (25+1)/2 = 13 
  x2 = (13+25/13)/2 = (13+1)/2 = 7
  x3 = (7+25/7)/2 = (7+3)/2 = 5
  x4 = (5+25/5)/2 = (5+5)/2 = 5
  x5 = (5+25/5)/2 = (5+5)/2 = 5  ...
Der Wert beleibt nun auf 5 stehen, dh, die Näherung ist abgeschlossen, wenn xn+1=xn wird. Anders ausgedrückt, Schluß ist wenn gilt:
  | xn+1 - xn | <= 0
==== sqrt ====
: sqrt	( n -- x ) 
  dup BEGIN 2dup / over + 2/  swap over - abs 1 <= UNTIL nip ;  
Um diesen Algorithmus zu entwickeln setzen wir die Näherungsformel zunächst in RPN um.
a xn /  xn +  2/  ==> xn+1
Dann erfolgt die Umsetzung in Forth. Dazu erstellen wir ein Stackbild der Operationen. Ausgangspunkt sind der Anfangswert n und der Schätrzwert x0.
   ( -- n x0 )
Diese müssen auf dem Stack für die Berechnung in der Schleife erhalten werden. Um daraus den Bruch n/xo zubilden, wird also zunächst verdoppelt und dann geteilt.
   2dup	 ( n x0 -- n x0 n x0 )
   /	 (      -- n x0 a    )
Nun kann x0 dazu addiert werden, anschließend wird durch 2 geteilt um den nächsten Schätzwert zu erhalten.
   over	 ( -- n x0 a x0  )
   +	 ( -- n x0 b     )
   2/	 ( -- n x0 x1    )
Der neue Schätzwert ersetzt nun den Alten.
   swap	 ( -- n x1 x0    )
Damit kann nun geprüft werden, ob die Annäherung an das Ergebnis schon erreicht worden ist.
   over		 ( -- n x1 x0 x1 )
   - abs 1 <=	 ( -- n x1 flag  )
Damit wird die Schleife solange durchlaufen, bis flag=true geworden ist, und wir haben x1=x als Ergebnis. Der Eingangswert n wird fallen gelassen.
                 ( -- n x1 )
   swap drop     ( -- x    )
Der Term swap drop ist, weil oft gebraucht, in manchen Forthsystemen  vorgefertigt und wird nip genannt.
  : nip 	swap drop ;
Achtung
In diesem Verfahren führen negative Eingangswerte zu einer Endlosschleife. Je nachdem welches Verhalten man für diesen Falle haben möchte, kann der Eingangswert zunächst abgefragt werden. So käme -24 throw in Frage: invalid numeric argument.
==== sqrt-2 ====
: sqrt-2	( n -- x ) 
  dup 0< IF -24 throw THEN
  dup BEGIN 2dup / over + 2/  swap over - abs 1 <= UNTIL nip ; 
==== sqrt-3 ====
: sqrt-3 ( u1 -- u2 )
  dup 0< IF -24 throw THEN
  dup begin  >r dup r@ /  r@ + 2/  dup r> - abs 2 < until  nip ;
===== unsigned integer square root (Wil Baden) =====
Soll hingegen ohne Vorzeichen gerechnet werden, wird gern das folgende Verfahren genommen, weil es so einfach ist. Es hat allerdings den Nachteil für größere Eingangswerte relativ langsam zu sein, da n-te wurzel + 1 Näherungsschritte erforderlich sind. 
[[proof of sqrt baden|proof of square root (W.Baden)]]
\ Paul E Bennet comp.arch.embedded 4 May 2008
\ Wil Baden; comp.lang.forth; "Square Root the Slow Way"
\ square root unsignd integer
: sqrt  -1 swap over do  2 +  dup  +loop  2/ ;
"It is a standard method of calculating square root by summing 
the odd integers. It works for all unsigned integers from 
0 to FFFFFFFF (or FFFF). 
I discovered the Forth code when implementing the sum of odd 
integers algorithm. It is neat how the Forth primitives work 
to implement this algorithm."
   zb gforth (cell=4; 32bit Sytem):
   -1 sqrt-pb u. 65535  ok 
Hierbei wird also vorzeichenlos eine Näherung ermittelt.
===== Weitere Verfahren =====
==== isqrt und sqrt-tab (bushmils) ====
: ISQRT ( n -- isqrt )
	DUP 0= ?EXIT
	DUP >R 
	BEGIN	R@ OVER /  OVER +  2/
	  	DUP ROT - ABS 1 <=
	UNTIL	R> DROP ;
Das "Problem" hierbei ist, dass es 52 Stellen gibt, wo der ISQRT einen anderen Wert liefert als FSQRT FROUND F>S .
Mit etwas mehr data space geht es schneller, wenn man z.B. eine 64K Tabelle anlegt:
\ gforth compatibility for testing:
: -R	postpone r> postpone drop ; immediate
256 dup *  constant #256  ( 64K)
CREATE sqrdtab #256 CELLS ALLOT
	MARKER -nonce  :NONAME   #256 0 DO  I I *   sqrdtab  I CELLS + !  LOOP ; EXECUTE -nonce
: SQRT-TAB ( x -- sqrt[x] ) 
	>R  #256 -1 		 	\ initialize lower and upper limits
	BEGIN	2DUP - 1 >		\ not yet done?	
	WHILE	2DUP + 2/		\ compute midpoint ( hi low mid )
	        DUP CELLS sqrdtab + @ 
		R@ U<= IF NIP		\ replace lower limit
	             ELSE ROT DROP SWAP	\ replace upper limit
	            ENDIF  ( cr .s )
	REPEAT	-R NIP   
	DUP -1 = IF  1+ EXIT  ENDIF ;
==== 32bit sqrt auf 16bit Maschine (Klaus Kohl) ====
\ Quelle: 4d1992_3.pdf; Fouriertransformation, Klaus Kohl. Screen#5 23.05.89/KK
( SQRT)
( Quadratwurzel einer 32-Bit-Integerzahl)
( Zulässiger Bereich: $3FFF.0001 -> 0..32767  ( 15 Bit )
( : under 	swap over ; )
: u2/	( u - u/2 )  2/ $7FFF and ;		  ( lower 15 bit erhalten )
: d2*   ( d - d*2 )  over 2* -rot 2* swap 0< - ;  ( Bit 15 übertragen )
: d2/   ( d - d/2 )  under 2/ swap u2/ rot 1 and IF $8000 or THEN swap ;
: d-    dnegate d+ ;
: SQRT-kk ( ud - u )
  0 0
  15
  FOR 	>r 2* over 0< - 2* over 2* 0< -		( 2 bits in S )
		>r d2* d2* r> r>		( Quadrat*4)
	2* 1+					( Wert*2+1)
	2dup u<					( Summe kleiner Wurzel?)
	IF 1-					( dann nur Wert*2 )
	ELSE dup >r - r> 1+			( oder Summe=Differenz)
	THEN
        NEXT
  nip nip nip U2/ ;
===== Aufgaben =====
  * Welcher Algorithmus steckt jeweils dahinter?
  * Wieso terminiert die Schleife immer? Gibt es kein Oszillieren?
  * Funktioniert das mit vorzeichenlosen und vorzeichenbehafteten Zahlen?
  * Wie sieht es mit dem Zeitverhalten aus? Wie oft wird die Schleife durchlaufen?
( gforth, 32bit System)
: test  ( von bis -- )
  swap DO cr i .
  i sqrt .
  i s>d d>f fsqrt fdup FROUND F>d d>s . f. 
  LOOP ;
===== Dank & Links =====
Für die ursprüngliche Anlage, hilfreiche Kritik und weitere Entwicklung meinen Dank an: Bernd, dmichelsen, uho, mhx, bushmills.
usenet:
   * comp.arch.embedded
   * comp.lang.forth