function bcroot($幂, $指 = '3', $scale = 0){
#开方
$d = false;
if($幂 == '0'){
return '0';
}elseif($幂 == '1'){
return '1';
}
$指数 = intval($指);
$底扩位数 = $scale;
$幂扩位数 = $指数 * $底扩位数;
$幂 = bcmul($幂,str_pad('1',$幂扩位数+1,'0'));
$小数点位 = strpos($幂,'.');
if($小数点位 !== FALSE){
$幂 = substr($幂,0,$小数点位);
}
$幂长 = strlen($幂);
$底数长 = ceil($幂长 / $指数);
#初次逆序
$幂 = strrev($幂);
$幂段 = array_reverse(str_split($幂,$指数));
$底数 = '';
$小余 = '0';
foreach($幂段 as $小幂){
#再次逆序,则正过来
$小幂 = strrev($小幂);
# (底 . 小底)^指数 - 小底^指数 <= 小余 . 小幂
if($小余 != '0'){
$此幂 = $小余.$小幂;
}else{
$此幂 = $小幂;
}
$小余 = '0';
$小底 = '1';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# x<1
$小底 = '0';
$小余 = $此幂;
}else{
# 1<x
$小底 = '9';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '-1'){
# 9<x
$小底 = '9';
$小余 = bcsub($此幂,${'试幂'.$小底});
}else{
# 1<x<9
$小底 = '5';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# 1<x<5
$小底 = '3';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# 1<x<3
$小底 = '2';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# 1<x<2
$小底 = '1';
$小余 = bcsub($此幂,${'试幂'.$小底});
}else{
# 2<x<3
$小底 = '2';
$小余 = bcsub($此幂,${'试幂'.$小底});
}
}else{
# 3<x<5
$小底 = '4';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# 3<x<4
$小底 = '3';
$小余 = bcsub($此幂,${'试幂'.$小底});
}else{
# 4<x<5
$小底 = '4';
$小余 = bcsub($此幂,${'试幂'.$小底});
}
}
}else{
# 5<x<9
$小底 = '7';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# 5<x<7
$小底 = '6';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# 5<x<6
$小底 = '5';
$小余 = bcsub($此幂,${'试幂'.$小底});
}else{
# 6<x<7
$小底 = '6';
$小余 = bcsub($此幂,${'试幂'.$小底});
}
}else{
# 7<x<9
$小底 = '8';
${'试幂'.$小底} = bcpow_sub($底数,$小底,$指);
$比较 = bccomp(${'试幂'.$小底},$此幂);
if($比较 == '1'){
# 7<x<8
$小底 = '7';
$小余 = bcsub($此幂,${'试幂'.$小底});
}else{
# 8<x<9
$小底 = '8';
$小余 = bcsub($此幂,${'试幂'.$小底});
}
}
}
}
}
$底数 .= $小底;
}
$底数 = bcdiv($底数,str_pad('1',$底扩位数+1,'0'),$scale);
return $底数;
}
function bcpow_sub($底,$小底,$指){
if($底 == '0' or $底 == ''){
return bcpow($小底,$指);
}else{
return bcsub(bcpow($底 . $小底,$指),bcpow($底 .'0',$指));
}
}