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

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

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

图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,符合预期。
 

永夜