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

 

转载于:https://my.oschina.net/u/2356887/blog/2252710

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值