PHP Conference Japan 2024

bcadd

(PHP 4, PHP 5, PHP 7, PHP 8)

bcadd添加两个任意精度的数字

描述

bcadd(字符串 $num1, 字符串 $num2, ?整数 $scale = null): 字符串

num1num2 相加。

参数

num1

左操作数,字符串类型。

num2

右操作数,字符串类型。

scale
此参数用于设置结果中小数点后的位数。如果为 null,则默认为使用 bcscale() 设置的默认比例,或回退到 bcmath.scale INI 指令的值。

返回值

两个操作数的和,字符串类型。

错误/异常

此函数在以下情况下抛出 ValueError 异常

  • num1num2 不是格式良好的 BCMath 数字字符串。
  • scale 超出有效范围。

变更日志

版本 描述
8.0.0 scale 现在可以为空。

范例

示例 #1 bcadd() 示例

<?php

$a
= '1.234';
$b = '5';

echo
bcadd($a, $b); // 6
echo bcadd($a, $b, 4); // 6.2340

?>

参见

  • bcsub() - 从另一个任意精度的数字中减去一个任意精度的数字

添加注释

用户贡献的注释 2 条注释

23
Nitrogen
15 年前
我创建了这个函数来将任意数量的数字加在一起。

这对于那些没有 BCMath 扩展的用户可能很有用。

它允许使用小数,并且具有可选的 $Scale 参数。如果未指定 $Scale,则它将自动调整以显示正确的小数位数。

<?php

function Add($Num1,$Num2,$Scale=null) {
// 检查是否是有效的正数,提取整数和小数部分
if(!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num1,$Tmp1)||
!
preg_match("/^\+?(\d+)(\.\d+)?$/",$Num2,$Tmp2)) return('0');

// 存储结果
$Output=array();

// 去除小数末尾的零并去除小数点
$Dec1=isset($Tmp1[2])?rtrim(substr($Tmp1[2],1),'0'):'';
$Dec2=isset($Tmp2[2])?rtrim(substr($Tmp2[2],1),'0'):'';

// 计算小数部分的最大长度
$DLen=max(strlen($Dec1),strlen($Dec2));

// 如果 $Scale 为 null,则自动将其设置为小数位数以保证精度
if($Scale==null) $Scale=$DLen;

// 去除整数部分前导零并反转,然后在末尾追加填充的小数部分
$Num1=strrev(ltrim($Tmp1[1],'0').str_pad($Dec1,$DLen,'0'));
$Num2=strrev(ltrim($Tmp2[1],'0').str_pad($Dec2,$DLen,'0'));

// 计算需要处理的最大长度
$MLen=max(strlen($Num1),strlen($Num2));

// 填充两个数字,使其长度相等(都等于 $MLen)
$Num1=str_pad($Num1,$MLen,'0');
$Num2=str_pad($Num2,$MLen,'0');

// 处理每一位数字,保留个位数,进位十位数(余数)
for($i=0;$i<$MLen;$i++) {
$Sum=((int)$Num1{$i}+(int)$Num2{$i});
if(isset(
$Output[$i])) $Sum+=$Output[$i];
$Output[$i]=$Sum%10;
if(
$Sum>9) $Output[$i+1]=1;
}

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

// 从结果中提取小数位数,如果需要则进行填充(如果 $Scale > 实际小数位数)
// 接下来,由于实际的零值可能会导致子字符串值出现问题,如果是这种情况,则只需简单地给出 '0'
// 接下来,如果定义了 $Scale,则追加小数部分,并返回结果
$Decimal=str_pad(substr($Output,-$DLen,$Scale),$Scale,'0');
$Output=(($MLen-$DLen<1)?'0':substr($Output,0,-$DLen));
$Output.=(($Scale>0)?".{$Decimal}":'');
return(
$Output);
}

$A="5650175242.508133742";
$B="308437806.831153821478770";

printf(" Add(%s,%s);\r\n// %s\r\n\r\n",$A,$B, Add($A,$B));
printf("BCAdd(%s,%s);\r\n// %s\r\n\r\n",$A,$B,BCAdd($A,$B));

/*
这将产生以下结果…
Add(5650175242.508133742,308437806.831153821478770);
// 5958613049.33928756347877

BCAdd(5650175242.508133742,308437806.831153821478770);
// 5958613049
*/

?>

制作这个过程很有趣,我想分享一下。
请享用,
Nitrogen。
9
Bo Anders Svensson
19年前
注意

$exp1 = "1E5";
$exp2 = "2E4";

$ans1 = bcadd((float)$exp1, (float)$exp2, 3);
$ans2 = bcadd((int)$exp1, (int)$exp2, 3);
$ans3 = bcadd($exp1, $exp2, 3);

echo "1: $exp1 + $exp2 = $ans1\r\n";
echo "2: $exp1 + $exp2 = $ans2\r\n";
echo "3: $exp1 + $exp2 = $ans3\r\n";

1: 1E5 + 2E4 = 120000.000
2: 1E5 + 2E4 = 3.000
3: 1E5 + 2E4 = 0.000
To Top