PHP 的 BCMath 函数中有一个错误bcmul
。它在 PHP 5.5.7 中仍然存在,这是撰写本文时的最新稳定版本。
如果您浏览源代码(PHP 5.5 的 BCMath recmul.c),您将看到相关函数:
void
bc_multiply (bc_num n1, bc_num n2, bc_num *prod, int scale TSRMLS_DC)
{
bc_num pval;
int len1, len2;
int full_scale, prod_scale;
/* Initialize things. */
len1 = n1->n_len + n1->n_scale;
len2 = n2->n_len + n2->n_scale;
full_scale = n1->n_scale + n2->n_scale;
prod_scale = MIN(full_scale,MAX(scale,MAX(n1->n_scale,n2->n_scale)));
/* Do the multiply */
_bc_rec_mul (n1, len1, n2, len2, &pval, full_scale TSRMLS_CC);
/* Assign to prod and clean up the number. */
pval->n_sign = ( n1->n_sign == n2->n_sign ? PLUS : MINUS );
pval->n_value = pval->n_ptr;
pval->n_len = len2 + len1 + 1 - full_scale;
pval->n_scale = prod_scale;
_bc_rm_leading_zeros (pval);
if (bc_is_zero (pval TSRMLS_CC))
pval->n_sign = PLUS;
bc_free_num (prod);
*prod = pval;
}
注:“刻度”一词是指分隔符后的位数。
看一下prod_scale
分配的行。当您调用 时bcmul("0.3", "0.2", 4)
,遍历代码,我们看到:prod_scale = MIN(2,MAX(4,MAX(1,1)));
,因此prod_scale
被赋值为2
。
而且,正如预期的那样,该函数返回一个小数点后两位而不是四位的值。与其他 BCMath PHP 函数不同(例如,参见 PHP 5.5 的 BCMath doaddsub.c的第 63-98 行),在此函数的逻辑中没有任何地方附加尾随零。
我已经向 PHP 错误跟踪系统 ( #66364 ) 提交了这个问题和一个补丁。