PHP BCMath 无法处理指数数,如果它被传递给它的函数,PHP BCMath return “ bcmath 函数参数不是 well-formed”
PHP BCMath cannot handle the exponential number if it is passed to its function, PHP BCMath return " bcmath function argument is not well-formed"
我正在处理一些小数,例如 0.0000687、0.0000063241、0.0000454。我使用 BCMath 来获得最精确的结果,因为它涉及金钱计算,到目前为止,BCMath 对我修复我之前遇到的错误非常有帮助。但是我发现,如果将 PHP 自动转换的指数值传递给 BCMath,BCMath 将无法正常工作。下面是示例代码:
$x = 0.00002123; // let say I got this value from the other computation;
// this $x value will automatically turn to exponential
// value by php because it have few of leading 0 after the '.'
PHP开始将其实数转换为指数的模式是:(见下图)
从上图中可以看出,PHP开始将实数转换为指数的模式是当前导0数为4次时-> 0.0000xxxxx(模式其中PHP 开始转换为指数)。
然后,假设这个变量 $x 将计算为 PHP BCMath 函数之一:
# First, I work with float number
$calculation1 = bcadd($x,5,12); // adding variable $x to 5
$calculation2 = bcmul($x,4,12); // multiply variable $x to 4
$calculation3 = bcdiv($x,5,12); // divide variable $x to 5
# Second, I tried to work with string number
$y = (string) $x;
$calculation4 = bcadd($y,5,12);
$calculation5 = bcmul($y,4,12);
$calculation6 = bcmul($y,4,12);
结果出错,这里是变量$x的截图:
这里的结果是错误的,这里是变量 $y 的屏幕截图(首先传递给字符串,因为 BCMath 可以很好地处理字符串):
重要提示 :
- 所以事实证明 BCMath 在处理指数值时有问题,我无法避免这个指数值,因为 PHP 会在达到其模式时自动将其解析为指数数(可以参见我上面附上的图片) .
- 考虑到变量 $x 我从不同的计算中得到的位置,所以在实际代码中,我不能真正将它硬编码为我想要的方式。
PHP 中的 bcmath 函数处理数字字符串。不是浮点数,重要的是,不是已转换为字符串的浮点数。 extension's introduction:
中提到了这一点
Valid (aka. well-formed) BCMath numbers are strings which match the regular expression /^[+-]?[0]*[1-9]*[.]?[0-9]*$/
.
将浮点数转换为 PHP 中的字符串通常会以科学记数法给出结果 - 您在结果中看到的 2.123E-5
语法。 bcmath 无法使用此表示;要匹配上面的正则表达式,字符串必须包含 十进制形式 .
的参数
您看到的警告是在 PHP 7.4 中添加的,并列在该版本的 Backward Incompatible Changes 页面上。以前任何格式不正确的参数都被默默地解释为零(这并不是很有帮助)。
如评论中所述,将浮点数转换为其十进制形式的最简单方法是使用 number_format
,提供与 bc 函数已经使用的精度相同的精度:
$precision = 12;
$x = 0.00002123;
echo bcadd(number_format($x, $precision), 5, $precision);
5.000021230000
我正在处理一些小数,例如 0.0000687、0.0000063241、0.0000454。我使用 BCMath 来获得最精确的结果,因为它涉及金钱计算,到目前为止,BCMath 对我修复我之前遇到的错误非常有帮助。但是我发现,如果将 PHP 自动转换的指数值传递给 BCMath,BCMath 将无法正常工作。下面是示例代码:
$x = 0.00002123; // let say I got this value from the other computation;
// this $x value will automatically turn to exponential
// value by php because it have few of leading 0 after the '.'
PHP开始将其实数转换为指数的模式是:(见下图)
从上图中可以看出,PHP开始将实数转换为指数的模式是当前导0数为4次时-> 0.0000xxxxx(模式其中PHP 开始转换为指数)。
然后,假设这个变量 $x 将计算为 PHP BCMath 函数之一:
# First, I work with float number
$calculation1 = bcadd($x,5,12); // adding variable $x to 5
$calculation2 = bcmul($x,4,12); // multiply variable $x to 4
$calculation3 = bcdiv($x,5,12); // divide variable $x to 5
# Second, I tried to work with string number
$y = (string) $x;
$calculation4 = bcadd($y,5,12);
$calculation5 = bcmul($y,4,12);
$calculation6 = bcmul($y,4,12);
结果出错,这里是变量$x的截图:
这里的结果是错误的,这里是变量 $y 的屏幕截图(首先传递给字符串,因为 BCMath 可以很好地处理字符串):
重要提示 :
- 所以事实证明 BCMath 在处理指数值时有问题,我无法避免这个指数值,因为 PHP 会在达到其模式时自动将其解析为指数数(可以参见我上面附上的图片) .
- 考虑到变量 $x 我从不同的计算中得到的位置,所以在实际代码中,我不能真正将它硬编码为我想要的方式。
PHP 中的 bcmath 函数处理数字字符串。不是浮点数,重要的是,不是已转换为字符串的浮点数。 extension's introduction:
中提到了这一点Valid (aka. well-formed) BCMath numbers are strings which match the regular expression
/^[+-]?[0]*[1-9]*[.]?[0-9]*$/
.
将浮点数转换为 PHP 中的字符串通常会以科学记数法给出结果 - 您在结果中看到的 2.123E-5
语法。 bcmath 无法使用此表示;要匹配上面的正则表达式,字符串必须包含 十进制形式 .
您看到的警告是在 PHP 7.4 中添加的,并列在该版本的 Backward Incompatible Changes 页面上。以前任何格式不正确的参数都被默默地解释为零(这并不是很有帮助)。
如评论中所述,将浮点数转换为其十进制形式的最简单方法是使用 number_format
,提供与 bc 函数已经使用的精度相同的精度:
$precision = 12;
$x = 0.00002123;
echo bcadd(number_format($x, $precision), 5, $precision);
5.000021230000