【问题标题】:PHP BCMath cannot handle the exponential number if it is passed to its function, PHP BCMath return " bcmath function argument is not well-formed"如果将指数数传递给它的函数,PHP BCMath 无法处理,PHP BCMath 返回“bcmath 函数参数格式不正确”
【发布时间】:2021-06-15 20:36:51
【问题描述】:

我正在研究少数小数,例如 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 的模式开始将实数转换为指数数” - PHP 内部没有转换任何东西,这只是表示如此微小的数字,当您以文本形式输出它们时。
  • 在字符串值不是一个数字,但你正试图这样对待它,这似乎是这里的实际问题。
  • 真正的问题在这里,如何使它与 bcmath 一起工作,你可以在你的环境中尝试,你可以复制我上面写的完全相同的代码/截图
  • 您可以通过使用实际数字而不是包含看起来像数字的内容的字符串来使其工作。
  • @CBroe 最后的评论可能有点苛刻,因为代码本身就在截图旁边的问题中。

标签: php laravel php-7 bcmath


【解决方案1】:

PHP 中的 bcmath 函数使用数字字符串。不是浮点数,重要的是,不是被强制转换为字符串的浮点数extension's introduction中提到了这一点:

有效的(又名格式良好的)BCMath 数字是匹配正则表达式 /^[+-]?[0]*[1-9]*[.]?[0-9]*$/ 的字符串。

在 PHP 中将浮点数转换为字符串通常会给您一个科学计数法的结果 - 您在结果中看到的 2.123E-5 语法。 bcmath 无法使用此表示;为了匹配上面的正则表达式,字符串必须包含 十进制形式的参数。

您看到的警告是在 PHP 7.4 中添加的,并列在该版本的 Backward Incompatible Changes 页面上。以前,任何非格式正确的参数都被默默地解释为零(这并不完全有帮助)。

如 cmets 中所述,将浮点数转换为十进制形式的最简单方法是使用 number_format,提供与 bc 函数相同的精度:

$precision = 12;
$x = 0.00002123;
echo bcadd(number_format($x, $precision), 5, $precision);

5.000021230000

https://3v4l.org/SuWIu

【讨论】:

    猜你喜欢
    • 2011-02-13
    • 2011-06-11
    • 2018-04-16
    • 2012-07-26
    • 2016-09-13
    • 2012-05-18
    • 2016-10-02
    • 2013-07-22
    • 1970-01-01
    相关资源
    最近更新 更多