bcmath 扩展提供了一套bc(Binary Calculator)数学函数,它是一个高精度运算的函数库,可以准确地对任意精度的数字进行运算。
对于十进制的浮点数,计算机底层无法准确用二进制进行存储,也就是说,计算机用二进制存储浮点数时,可能出现精度丢失的问题。当我们用常规的方式(加减乘除、幂运算、求平方根)对浮点数进行运算时,就可能出现计算结果不准确的问题。这种精度计算的问题是计算机底层的一个bug,是跨语言的。
示例1:
$f = 0.58;
var_dump($f * 100);
var_dump(round($f * 100));
var_dump(intval($f * 100));
var_dump($f * 100==58);
var_dump(round($f * 100)==58);
var_dump(intval($f * 100)==58);
// 输出:float(58) float(58) int(57) bool(false) bool(true) bool(false)
可以发现,0.58*100的结果并不等于58,只是近似58而已。因为,浮点数0.58在计算机中无法准确存储,计算机中实际存储的值是0.5799999999999999999,它只能无限接近于0.58。
示例2:
0.1+0.2 == 0.3);
// 输出:bool(false)
示例3:
$a = 0.1+0.2;
printf('%.18f', $a);
echo '
';
$b = 0.3;
printf('%.18f', $b);
echo '
';
var_dump($a==$b);
// 输出结果如下:
0.300000000000000044
0.299999999999999989
bool(false)
问题在于:看似有穷的浮点数,在计算机的二进制表示中却是无穷的。
为此,大部分语言都提供了精准计算的类库或函数库,比如php有BC高精度运算函数库。
注意: 在对浮点数进行运算或比较时,推荐使用bc数学函数。
BC数学函数仅在 PHP 编译时配置了 --enable-bcmath 时可用。
PHP 的 Windows 版本已内建对此扩展的支持。
PHP 的 Linux 版本,则需要手动安装bcmath扩展。
在PHP的源码包中,默认就包含bcmath扩展的安装文件,只需手动安装一下即可。
cd /soft/php-5.5.38/ext/bcmath
// 进入PHP的源码包目录中的bcmatch扩展目录
/usr/local/php-5.5.38/bin/phpize
// 执行phpize命令
./configure --with-php-config=/usr/local/php-5.5.38/bin/php-config
// 配置
make && make install
// 编译和安装
安装完成后,可以得到bcmath.so文件,将该文件拷贝至php的扩展存放目录。
然后,修改php的配置文件php.ini,加入如下的代码:
extension=bcmath.so
最后,重启php服务即可。
原型:string bcadd ( string $left_operand , string $right_operand [, int $scale ] )
功能:2个任意精度数字的加法计算。
参数:
用法示例:
$a = bcadd(0.1, 0.2);
echo $a .' ';
echo bcadd(0.1, 0.2, 5) .' ';
$b = 0.3;
var_dump($a==$b);
// 输出:0.30 0.30000 bool(true)
原型:bool bcscale ( int $scale )
功能:设置所有bc数学函数的未设定情况下的小数点保留位数。
用法示例:
3);
echo bcadd(0.1, 0.2);
// 输出:0.300
原型:string bcsub ( string $left_operand , string $right_operand [, int $scale = int ] )
功能:2个任意精度数字的减法计算。
用法示例:
echo bcsub(0.2, 0.1);
// 输出:0.100
原型:string bcmul ( string $left_operand , string $right_operand [, int $scale = int ] )
功能:2个任意精度数字的乘法计算。
用法示例:
echo bcmul(0.2, 0.1);
// 输出:0.02
功能:2个任意精度数字的除法计算。
用法示例:
echo bcdiv(0.2, 0.1);
// 输出:2.000
原型:int bccomp ( string $left_operand , string $right_operand [, int $scale = int ] )
功能:比较两个任意精度的数字大小。
返回值:如果两个数相等返回0,左边的数比右边的数大返回1,否则返回-1。
用法示例:
echo bccomp(0.1, 0.2);
// 输出:-1
原型:string bcmod ( string $left_operand , string $modulus )
功能:对一个任意精度数字取模。
原型:string bcpow ( string $left_operand , string $right_operand [, int $scale ] )
功能:求任意精度数字的乘方(幂运算)。
原型:string bcsqrt ( string $operand [, int $scale ] )
功能:求任意精度数字的平方根。