← PHP prev()函数:数组内部指针回退一位的用法与边界处理 没有下一篇了 →

PHP array_product()函数:计算数组元素乘积的用法与实战注意点

著
原创 2026-10-08 PHP 已有人查阅

一、array_product()是做什么的

PHP里算数组元素之和有array_sum(),算乘积有array_product()。后者把数组里每个元素依次相乘,返回最终结果。

函数原型:

number array_product(array $array);

参数只有一个,必填,是要计算的数组。返回类型是int或float,取决于计算结果是否超出整数范围或包含浮点数。

基础用法:

$prime = array(2, 3, 5, 7);
echo array_product($prime); // 210

2×3×5×7=210。数组有几个元素就乘几次,顺序不影响结果。

浮点数也能算:

$num = array(1.1, 2.2, 3.3);
echo array_product($num); // 7.986

结果返回float。只要数组里有一个浮点数,最终结果通常就是float,除非乘积恰好是整数值。

二、空数组返回1,这个设计有讲究

对空数组调array_product(),返回1,不是0。

$empty = array();
var_dump(array_product($empty)); // int(1)

这个行为来自数学上的“空积”约定。乘法单位元是1,空数组没有元素可乘,返回单位元1,这样嵌套计算时不会破坏结果。对比array_sum(),空数组返回0,因为加法的单位元是0。

我在做一个统计模块时踩过这个坑。代码逻辑是“把一组比例因子相乘得到总系数”,数组从数据库查出来可能是空的。当时想当然以为空数组返回0,结果总系数变成1,后续计算全偏了。后来加了判断:

$factors = array();
if (empty($factors)) {
    // 单独处理,不直接乘
} else {
    $total = array_product($factors);
}

空数组返回1这件事,用之前得知道,否则容易在业务逻辑里留下隐患。

三、非数值元素会被隐式转换

array_product()不检查元素类型,它按PHP的数值转换规则处理每个元素。

$mixed = array(2, "3", "code", true, null);
echo array_product($mixed); // 0

逐个看:

  • 2是整数2

  • "3"是数字字符串,转成3

  • "code"不是数字字符串,转成0

  • true转成1

  • null转成0

乘到"code"的时候结果已经是0,后面全是0。所以最终返回0。

如果数组里混了非数值字符串,结果往往是0,但这不代表计算“失败”,函数只是按规则转换了。如果业务上不允许非数值元素,得自己先过滤:

$data = array(2, "3", "code", 5);
$filtered = array_filter($data, 'is_numeric');
echo array_product($filtered); // 30

array_filter()配合is_numeric()能把非数值元素去掉。这一步在数据来自用户输入或外部接口时比较有必要。

四、大数溢出和精度问题

PHP的整数有范围限制,64位系统上较大约9.2×10^18。乘积超过这个范围,结果会自动转成float。

$big = array(1000000, 1000000, 1000000);
var_dump(array_product($big)); // float(1.0E+18)

三个一百万相乘是10^18,接近整数上限但还没超,PHP可能返回int也可能返回float,取决于具体平台和版本。再多乘一个就明确是float了。

$bigger = array(1000000, 1000000, 1000000, 1000000);
var_dump(array_product($bigger)); // float(1.0E+24)

float有精度限制,大约15到17位有效数字。超过之后结果不再精确。做阶乘、排列组合这类计算时,大数乘积用array_product()只能得到近似值。

需要精确大数运算,得用BCMath或GMP扩展:

$nums = array("1000000", "1000000", "1000000", "1000000");
$result = "1";
foreach ($nums as $n) {
    $result = bcmul($result, $n);
}
echo $result; // 1000000000000000000000000

BCMath用字符串存数字,不受浮点精度影响。代价是速度比原生运算慢。如果业务对精度有要求,比如金额、库存、科学计算,别用array_product()。

五、和array_sum()的对称与差异

array_product()和array_sum()是一对,一个乘一个加,但行为上有几处不同:

对比项 array_product() array_sum()
空数组返回 1 0
非数值字符串 转0,乘积为0 转0,不影响和
大数溢出 转float,可能失精 转float,可能失精
返回类型 int或float int或float

关键差异在非数值元素的影响。array_sum()里一个"code"转成0,其他数值照常相加,结果可能还有意义。array_product()里一个"code"转成0,整个乘积直接归零。这个差别让array_product()对数据质量更敏感。

我在处理用户提交的多选评分时遇到过类似情况。评分数组里混了空字符串,用array_product()算总权重,结果全是0。排查后发现是空选项没过滤。后来在入口处统一做了is_numeric校验,问题不再出现。

六、项目里的实际用法

计算折扣系数。电商场景里,多个折扣叠加,总折扣是各折扣率相乘:

$discounts = array(0.9, 0.95, 0.8);
$finalRate = array_product($discounts); // 0.684

九折、九五折、八折叠加,最终是原价的68.4%。这个用法比循环乘更简洁。

计算阶乘。给定n,生成1到n的数组,乘起来就是n的阶乘:

$n = 5;
$nums = range(1, $n);
echo array_product($nums); // 120

n小的时候够用,n大了会遇到溢出和精度问题,换BCMath。

计算概率连乘。多个独立事件同时发生的概率是各自概率的乘积:

$probs = array(0.5, 0.4, 0.3);
echo array_product($probs); // 0.06

这种场景结果通常很小,float精度够用。

几何平均数的中间步骤。几何平均数是所有数乘积的n次方根,array_product()可以算乘积部分:

$values = array(2, 8, 4);
$product = array_product($values); // 64
$geometricMean = pow($product, 1 / count($values)); // 4

一个踩坑记录。有次做库存预警,逻辑是“多个仓库库存比例相乘得到总体可用率”。数据库里某个仓库的比例字段是NULL,查出来放进数组,array_product()把NULL转成0,整个可用率变成0,预警全触发。排查时才发现NULL没处理。后来在查询层用COALESCE把NULL转成1,或者在PHP层用array_filter()过滤掉NULL,问题解决。

这个经历让我形成一个习惯:调array_product()之前,先确认数组里没有NULL、空字符串、非数值字符串。这些值会悄悄把结果变成0,而函数本身不会报错。

七、本节课程知识要点

  1. array_product()计算数组所有元素的乘积,返回int或float。

  2. 空数组返回1,这是乘法的单位元,不是错误,但业务上要留意。

  3. 非数值元素按PHP转换规则处理,非数值字符串转0,导致乘积归零。

  4. 大数乘积会转float,超过约15到17位有效数字后精度下降。

  5. 需要精确大数运算用BCMath或GMP,不要依赖array_product()。

  6. 和array_sum()的关键差异:空数组返回值不同,非数值元素对结果的影响程度不同。

  7. 调之前先过滤数据,用array_filter()配合is_numeric()排除无效元素,避免结果意外归零。

array_product()的用法直接,但它的几个隐式行为——空数组返回1、非数值转0、大数转float——决定了它在项目里不能拿来就用。数据来源越杂,越要先过滤。精度要求越高,越要考虑BCMath。它适合处理数值干净、量级可控的数组,比如折扣率、概率、小范围阶乘。超出这个范围,手写循环或用专门的数学库更稳。

← PHP prev()函数:数组内部指针回退一位的用法与边界处理 没有下一篇了 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号