[mercury-users] Functional square root approximation : help needed

Ralph Becket rbeck at microsoft.com
Thu Apr 26 23:42:18 AEST 2001


> % Mercurally speaking, this is:
> 
> :- mode sqrt_guess(in, in, out) is det.
> sqrt_guess(Y, X, NewGuess) :-
>     Quotient = X / Y,
>     NewGuess = (Y + Quotient) / 2
>     .

You can use functional style here:

:- func improve_guess(float, float) = float.

improve_guess(Guess, X) = (Guess + (X / Guess)) / 2.0.

Notice use of the float `2.0' rather than the int `2'.

> %  (define (sqrt-iter guess x)
> %   (if (good-enough? guess x)
> %       guess
> %       (sqrt-iter (improve guess x)
> %                  x)))
> 
> :- mode sqrt_iter(in, in, out) is det.
> sqrt_iter(Guess,X,Answer) :-
> 	  GoodEnough(Guess,X,Bool),
> 	  (
> 		Bool = yes,
> 		Answer = Guess
> 		;
> 		Bool = no,
> 		sqrt_guess(Guess,X,NewGuess),
> 		Answer = NewGuess
> 	  )
> 	  .

Here you've capitalised `GoodEnough', so the compiler thinks
it's a variable, making this an higher order predicate application.
Also, you've missed off the recursive case in the `Bool = no'
clause.

> :- mode GoodEnough(in, in, out) is det.
> GoodEnough(Guess,X,Bool) :-
> 		    Assessment = abs(Guess * Guess - X),
> 		    ( Assessment < 0.001,
> 		      Bool = yes
> 		      ;
> 		      Bool = no
> 		    )
> 		    .

Same here.

Instead, try

:- func sqrt_iter(float, float) = float.

sqrt_iter(Guess, X) =
	( if good_enough(Guess, X)
	  then Guess
	  else sqrt_iter(improve_guess(Guess, X), X)
	).

:- pred good_enough(float, float).
:- mode good_enough(in, in) is semidet.

good_enough(Guess, X) :-
	abs(Guess * Guess - X) < 0.001.

> :- mode main(in,out) is det.
> main(X,Answer) :- sqrt_iter(1.0,X,Answer).

It's a bad idea to use main/2 for anything other than the top-
level predicate in your program.  How about this:

:- func square_root(float) = float.

square_root(Num) = sqrt_iter(1.0, Num).

-- Ralph
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list