设计一个高精度加法的函数,支持长数字相加不损失精度,忽略负数(请不要使用 bcadd 等自带函数)

1、最近几天,在机试时候的一个面试题,设计一个高精度加法的函数,支持长数字相加不损失精度,忽略负数(请不要使用 bcadd 等自带函数)。

2、查看 PHP 官网,bcadd — 两个任意精度数字的加法计算。如图1

bcadd — 两个任意精度数字的加法计算

图1

3、最终实现代码如下,期待于后续有时间后继续完善,现阶段对于请求参数的容错处理上做得还不够,且不支持负数

<?php

function highPrecisionAdd(string $number1, string $number2, $scale = null) {

	// 提取出整数与小数
	$numArr1 = explode('.', $number1);
	$numArr2 = explode('.', $number2);

	$result = [];

	// 计算小数的最长长度
	$decimalMaxLen = max(strlen($numArr1[1]), strlen($numArr2[1]));

	// 判断 $scale 是否为 null,如果是,则设置其为结果中小数点后的小数位数
	if ($scale === null) {
		$scale = $decimalMaxLen;
	}
	

	// 删除前导零并反转整数,然后在末尾连接小数
	$number1 = strrev(ltrim($numArr1[0], '0') . str_pad($numArr1[1], $decimalMaxLen, '0'));
	$number2 = strrev(ltrim($numArr2[0], '0') . str_pad($numArr2[1], $decimalMaxLen, '0'));

	// 计算需要处理的最长长度
	$maxLen = max(strlen($number1), strlen($number2));

	// 填充两个数字,使它们的长度相等(都等于 $maxLen)
	$number1 = str_pad($number1, $maxLen, '0');
	$number2 = str_pad($number2, $maxLen, '0');

	// 处理每个数字,保留个位,携带十位(余数)
	for($i = 0; $i < $maxLen; $i++) {
		$sum = ((int) $number1[$i] + (int) $number2[$i]);
		if (isset($result[$i])) {
			$sum += $result[$i];
		}
		$result[$i] = $sum % 10;
		if ($sum > 9) {
			$result[$i + 1] = 1;
		}
	}

	// 将数组转换为字符串并将其反转
	$result = strrev(implode($result));

	// 计算出小数
	$decimal = str_pad(substr($result, -$decimalMaxLen, $scale), $scale, '0');
	
	// 计算出整数
	$can = (($maxLen - $decimalMaxLen < 1) ? '0' : substr($result, 0, -$decimalMaxLen));

	// 拼接整数与小数
	$result = $can . (($scale > 0) ? '.' . $decimal : '');

	return $result;
}

echo highPrecisionAdd('64474.47265', '24562.45124');
?>

4、64474.47265 与 24562.45124 相加,运行结果等于:89036.92389,符合预期。
 

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/250642.html

(0)
上一篇 2022年4月30日 00:32
下一篇 2022年4月30日 00:32

相关推荐

发表回复

登录后才能评论