« Measuring the speed of MySQL replication | Home | Fading alerts in JavaScript »
Find the square root of a number with any precision
function bcgetscale(){
return strlen(bcadd(1,0))-2;
}
//Version 0.2 of BCRoot
//By Chao XU
//From www.webdevlogs.com
//Change Log: It uses a lot bcsqrt() to make the speed fast
//fix a small decimal bug, where the last decimal could be wrong
function bcroot($a, $n, $scale='default'){
$default = bcgetscale();//Get the scale
if($scale == 'default'){
$scale = $default;//use default scale
}
if($n & ($n-1)){//check if $n is the power of 2, return 0 if is
//decbin is the reason this function can't have number
//larger than 2^31
$bin = decbin($n);
$i = strlen($bin)-1;
$pow = 0;
while($i){
if($bin[$i]==='0'){
++$pow; –$i;
}else{
break;
}
}
$n = bcdiv($n, bcpow(2, $pow),0);
//now use Newton’s method to find the number
bcscale($scale+15);
$x = 1;
$k = 0;
$limit = ceil(log($scale+15)/log(2))+1;
while($k<$limit){
$t1 = bcdiv(1,$n);
$t21 = bcmul(bcsub($n,1),$x);
$t22 = bcdiv($a,bcpow($x, $n-1));
$t2 = bcadd($t21,$t22);
$x = bcmul($t1, $t2);
++$k;
}
$i = 0;
while($i < $pow){
$x = bcsqrt($x,$scale+3);
++$i;
}
bcscale($default);
return bcadd($x,0,$scale);
}else{
//here use many bcsqrt, because this is FAST
$i = 0;
$pow = log($n)/log(2);
while($i < $pow){
$a = bcsqrt($a,$scale+3);
++$i;
}
return bcadd($a,0,$scale);
}
}
And now use it
$the_number = 3;
$the_nth_root = 12;
$the_precision = 30;
bcroot($the_number, $the_nth_root, $the_precision);
//returns 1.095872691135244380160019128072.
//Which is the 12th root of 3
Topics: PHP | Submitter: admin
Comments
You must be logged in to post a comment.