PHP中array_sum处理含科学计数法数组的求和异常问题
数组求和后强制转int出现异常的原因与解决办法
问题现象
数组中包含4.4002258020009E+26这个超大科学计数法数值时,使用array_sum求和后得到浮点数,再强制转换为int会出现异常负数结果;移除该数值后,求和转int结果正常。
相关代码:
$list = [ 700, 700, 200, 700, 2853300, 595300, 4736700, 1700, 4.4002258020009E+26, 200, 39800, 171002250300, 8410600, 100, 1000, 10000000000800, 100, 6000, 700, 100 ]; print_r($list); $sum = array_sum($list); echo "sum: $sum\n"; $sum = (int)$sum; echo "sum: $sum\n";
输出结果:
sum: 4.400225802001E+26 sum: -2402111299539435520
原因分析
- 浮点数精度与范围限制:
array_sum只要数组中存在浮点数,就会返回浮点数结果。4.4002258020009E+26远大于64位有符号整数最大值(约9e18),浮点数无法精确表示这么大的整数,强制转int时会触发整数溢出。 - 溢出后的补码表现:64位有符号整数溢出后,会按照补码规则循环,最终得到负数结果,这就是异常值的来源。
解决办法
方案1:移除超大数值(业务允许时)
直接删除数组中的4.4002258020009E+26元素,此时array_sum返回的数值在64位int范围内,强制转int即可得到正确结果:
$list = [ 700, 700, 200, 700, 2853300, 595300, 4736700, 1700, // 移除超大数值 200, 39800, 171002250300, 8410600, 100, 1000, 10000000000800, 100, 6000, 700, 100 ]; $sum = array_sum($list); echo "sum: $sum\n"; // 输出10171018899000 echo "sum: " . (int)$sum . "\n"; // 输出10171018899000
方案2:使用大数运算扩展(必须保留超大数值)
PHP的BCMath扩展支持高精度大数运算,通过字符串形式处理数值,避免浮点数精度损失和整数溢出:
$list = [ 700, 700, 200, 700, 2853300, 595300, 4736700, 1700, '440022580200090000000000000', // 用字符串表示超大数值,避免自动转为浮点数 200, 39800, 171002250300, 8410600, 100, 1000, 10000000000800, 100, 6000, 700, 100 ]; $sum = '0'; foreach ($list as $num) { $sum = bcadd($sum, (string)$num); // 逐个累加大数 } echo "sum: $sum\n"; // 输出准确的求和结果:440022580200100171018899000
注意:使用BCMath前需确保PHP已启用该扩展,可通过
phpinfo()查看扩展状态。
内容的提问来源于stack exchange,提问作者clarkk
相关产品推荐
相关产品推荐

