PHP高精度/金钱//数学函数库-bcmath

PHP 专栏收录该内容
288 篇文章 1 订阅

为什么要使用 bcmath

首先我们要明白为什么要使用 bcmath,因为我们平时没怎么使用它们,但是我们在做高精度计算,或者金钱计算的时候对结果要尽可能的精确且可控,但是编程语言对浮点数和大整数的运算,表示,存储方面都存在一定的问题,这个和语言无关。

先来看浮点数的问题

$f = 0.58;
$r = $f * 100;
var_dump($r); // float(58)
var_dump(intval($r)); // int(57)

首先就是你看到的和实际内存中存储的不一致,实际存储可能是 0.58 -> 0.57999999999999996,而 $r -> 57.999999999999996,这就出现了不可控,甚至到了不可用的地步。

其次是大的整数,而整数能存储的最大值是受操作系统限制的,比如有32位和64位系统之分,当你要存储的值超过了上限,那么就会被当做浮点数来存了,牵涉到浮点数就可能存在计算偏差。

$a = PHP_INT_MAX;  
$b = PHP_INT_MAX+1; 
var_dump($a); // int(2147483647)
var_dump($b); // float(2147483648)
var_dump($a === $b - 1); // bool(false)

针对以上的问题,可以使用字符串来存储浮点数和大整数。

$f = 0.58;
$r = strval($f*100);
var_dump(intval($r)); // int(58)

基于这样的思路,于是有了 PHP bcmath ,每个语言都有相对应的实现。

关于 bcmath (Binary Calculator)

对于任意精度的数学,PHP提供了支持用字符串表示的任意大小和精度的数字的二进制计算,最多为 2147483647-1(或0x7FFFFFFF-1)

本类函数仅在 PHP 编译时配置了 --enable-bcmath 时可用。PHP 的 Windows 版本已内建对此扩展的支持。不需要载入额外的扩展来使用这些函数。

它包含了如下的一些计算:相加,比较,相除,相减,求余,相乘,n次方,配置默认小数点数目,求平方等等。这些函数在涉及到有关金钱的计算时比较有用。

  • bcadd 相加
  • bccomp 比较两个任意精度的数字,结果 1,0,-1
  • bcdiv 2个任意精度的数字除法计算
  • bcmod 对一个任意精度数字取模
  • bcmul 2个任意精度数字乘法计算
  • bcpow 任意精度数字的乘方
  • bcpowmod 先乘方,再取模
  • bcscale 设置所有bc数学函数的默认小数点保留位数
  • bcsqrt 任意精度数字的二次方根
  • bcsub2个任意精度数字的减法

bcadd

2个任意精度数字的加法计算

bcadd ( string $left_operand , string $right_operand , int $scale = ? ) : string

int $scale此可选参数用于设置结果中小数点后的小数位数。也可通过使用 bcscale() 来设置全局默认的小数位数,用于所有函数。如果未设置,则默认为 0

$a = '1.234';
$b = '5.366';

var_dump(bcadd($a, $b));     // string(1) "6"
var_dump(bcadd($a, $b, 4));  // string(6) "6.6000"
$a = '1.2348111111111111111111';
$b = '5.3152222222222222222222';

var_dump(bcadd($a, $b));     // string(1) "6"
var_dump(bcadd($a, $b, 2));  // string(6) "6.55"

小数的位数是相加后四舍五入再来截取的,位数不够的补0

bccomp

比较两个任意精度的数字的大小

bccomp ( string $left_operand , string $right_operand , int $scale = int ) : int

可选的scale参数表示要以几位小数来比较。

如果两个数相等返回0, 左边的数left_operand比较右边的数right_operand大返回1, 否则返回-1

var_dump(bccomp('1', '2'));     // int(-1)
var_dump(bccomp('1.00001', '-1', 3));  // int(1)
var_dump(bccomp('1.00001', '1', 3));  // int(0)
var_dump(bccomp('1.00001', '1', 5));  // int(1)

bcdiv

2个任意精度的数字除法计算

bcdiv ( string $left_operand , string $right_operand , int $scale = int ) : string

scale此可选参数用于设置结果中小数点后的小数位数。也可通过使用 bcscale() 来设置全局默认的小数位数,用于所有函数。如果未设置,则默认为 0

var_dump(bcdiv('105', '6.55957', 3));  // 16.007

bcmod

对一个任意精度数字取模

bcmod ( string $left_operand , string $modulus ) : string

返回字符串类型取模后结果,如果系数为0则返回null

echo bcmod('4', '2'); // 0
echo bcmod('2', '4'); // 2

bcmul

2个任意精度数字乘法计算

bcmul ( string $left_operand , string $right_operand , int $scale = int ) : string
echo bcmul('1.34747474747', '35', 3); // 47.161
echo bcmul('2', '4'); // 8

bcpow

任意精度数字的乘方

bcpow ( string $left_operand , string $right_operand , int $scale = ? ) : string
echo bcpow('4.2', '3', 2); // 74.08

bcpowmod

先乘方,再取模

bcpowmod ( string $num , string $exponent , string $modulus , int|null $scale = null ) : string
var_dump(bcpowmod('3', '3', '2', 0));  // string(1) "1"

bcscale

设置所有bc数学函数的默认小数点保留位数

bcscale ( int $scale ) : bool

bcsqrt

任意精度数字的二次方根

bcsqrt ( string $operand , int $scale = ? ) : string

bcsub

2个任意精度数字的减法

bcsub ( string $left_operand , string $right_operand , int $scale = int ) : string

参考

https://www.laruence.com/2013/03/26/2884.html

https://www.laruence.com/2011/12/19/2399.html

  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值