BC開方(乙)

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',$指));
	}
}
相關文章
相關標籤/搜索