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',$指)); } }