use constant SQRT_EPSILON => 0.0001; use constant SQRT_MAX_ITER => 50; sub sqrt ($) { my $x = shift; return undef if $x < 0; my $base = 0; my $top = $x; my $guess = middle($base, $top); my $counter = SQRT_MAX_ITER; while (abs($x - square $guess) >= SQRT_EPSILON) { # Avoid looping for too long. return undef unless $counter--; if ( square $guess < $x ) { $base = $guess; $guess = middle( $guess, $top ); } elsif ( square $guess > $x ) { $top = $guess; $guess = middle( $base, $guess ); } } return $guess; }