如果将指数数传递给其函数,PHP BCMath 无法处理指数数,PHP BCMath 返回“bcmath 函数参数格式不正确”

问题描述 投票:0回答:2

我正在研究一些小数,例如 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 laravel php-7 bcmath
2个回答
13
投票

PHP 中的 bcmath 函数可处理数字字符串。不是浮点数,重要的是,不是已转换为字符串的浮点数。这在扩展的介绍中提到过

有效(又名格式正确)的 BCMath 数字是与正则表达式

/^[+-]?[0]*[1-9]*[.]?[0-9]*$/
匹配的字符串。

在 PHP 中将浮点数转换为字符串通常会给出科学记数法的结果 - 您在结果中看到的

2.123E-5
语法。 bcmath 无法使用此表示;为了匹配上面的正则表达式,字符串必须包含十进制形式的参数。

您看到的警告是在 PHP 7.4 中添加的,并列在该版本的“向后不兼容更改”页面上。以前,任何格式不正确的参数都会被默默地解释为零(这并不完全有帮助)。 如评论中所述,将浮点数转换为十进制形式的最简单方法是使用

number_format

,提供与 bc 函数已使用的相同精度:
$precision = 12; $x = 0.00002123; echo bcadd(number_format($x, $precision), 5, $precision);

5.000021230000

参见
https://3v4l.org/SuWIu


0
投票

$num_str = sprintf("%.12F", $value);

(其中 12 是您喜欢的任何精度,包括 {$ precision}。)但是,我已经看到如果 PHP 区域设置设置为不使用句点(点)作为小数点分隔符的位置,则会出现错误,其中如果您在上面接受的答案的评论中使用更正的解决方案,可能会更好。

© www.soinside.com 2019 - 2024. All rights reserved.