sifukurt has asked for the wisdom of the Perl Monks concerning the following question:

Good day, fellow monks. I've got a snippet of code that I'm hoping you can help me speed up. My code is to find the N-th root of a given number.
use Math::BigFloat; sub Root { my $num = shift; my $root = shift; my $iterations = shift || 5; if ( $num < 0 ) { return undef } if ( $root == 0 ) { return 1 } my $Num = Math::BigFloat->new( $num ); my $Root = Math::BigFloat->new( $root ); my $current = Math::BigFloat->new(); my $guess = Math::BigFloat->new( $num ** ( 1 / $root ) ); my $t = Math::BigFloat->new( $guess ** ( $root - 1 ) ); for ( 1 .. $iterations ) { $current = $guess - ( $guess * $t - $Num ) / ( $Root * $t ); if ( $guess eq $current ) { last } $t = $current**($root-1); $guess = $current; } return $current; }
This uses Newton's method for finding the roots. It produces very accurate results, provided you increase the number of iterations if you're dealing with large numbers and/or large roots. Therein lies the problem. If you want something relatively simply like the 5th root of 100:
$x = Root( 100, 5 );
the result is reasonably fast. However, with each iteration, it get progressively slower. So if you wanted something enormous, like:
$x = Root( 500000, 555 );
you could be waiting for ages. If we leave the number of iterations low, the result will likely be very inaccurate, but as we increase the number of iterations, each individual iteration gets slower and slower. The only thing I've been able to come up with so far is the comparison of $guess and $current inside the for loop. I was able to get a bit of a speed boost by doing a string comparison rather than a numeric comparison. Any suggestions on how to speed this up?


UPDATE: 28-Dec-2001 - I updated the above code to reflect the changes suggested by arhuman and Dominus. It is much more accurate and substantially faster now. Further optimization forthcoming....