官方介绍:http://www.php.net/manual/en/function.bccomp.php
中文介绍:http://php.freehostingguru.com/function.php-bccomp.php
bccomp
比较二个高精确度数字。
语法: int bccomp(string left operand, string right operand, int [scale]);
返回值: 整数
函数种类: 数学运算
此函数比较二个高精确度的数字。输入二个字符串,若二个字符串一样大则返回 0;若左边的数字字符串 (left operand) 比右边 (right operand) 的大则返回 +1;若左边的数字字符串比右边的小则返回 -1。scale 是一个可有可无的选项,表示返回值的小数点后所需的位数。
经过测试,前两个参数不管是字符还是浮点数都可以正常比对。使用== 或者 === 均不能比对浮点数,会出现时对时错的情况。谨记。
20161128:echo bccomp(123.1234,123.1235,3);
会返回0,表示想等,bccomp不会四舍五入。
2016-11-24 更新 (字符串比对的坑)
$a='70001502570002755697';
$b='70001502570002759229';
if($a==$b){
echo 1;
}else{
echo 2;
}
以上的代码返回的结果将是“1”,这是由于php将数字类型字字符串转换为数字类型,而int类型是有精度的,经过测试,精度为16位。
如果去掉一位数字,改成以下代码,将会输出“2”,因为第16位变为不等了。
$a='0001502570002755697';
$b='0001502570002759229';
if($a==$b){
echo 1;
}else{
echo 2;
}
学艺不精,耽误了好多时间,解决问题的方法是使用strcmp(string1,string2)
strcasecmp(string1,string2)
前者大小写敏感,后者大小写不敏感。
2016-11-26 更新
使用phpexcel读取excel账单时,读取的浮点数会产生异常情况
$item = array(
'bill_id' => $currentSheet->getCell("A".$line)->getValue(),//网关接入号
'bill_type' => $currentSheet->getCell("H".$line)->getValue(),//交易状态 成功 失败 。退款类型:部分退款,全额退款
'bill_time' => date("Y-m-d H:i:s", substr(PHPExcel_Shared_Date::ExcelToPHP($currentSheet->getCell("M".$line)->getValue()),0,19)),//交易时间
'gleepay_id' => $currentSheet->getCell("B".$line)->getValue(),
'payment_id' => $currentSheet->getCell("C".$line)->getValue(),
'order_time' => date("Y-m-d H:i:s", substr(PHPExcel_Shared_Date::ExcelToPHP($currentSheet->getCell("N".$line)->getValue()),0,19)),//处理时间
'purchase_curr' => $currentSheet->getCell("D".$line)->getValue(),
'purchase_amount' => $currentSheet->getCell("E".$line)->getValue(),
'checkout_curr' => $currentSheet->getCell("F".$line)->getValue(),
'checkout_amount' => $currentSheet->getCell("G".$line)->getValue(),
'bill_amount' => '0', //订单金额
'business' => '0' //1:交易。0:退款。
);
其中交易金额和结单金额等数字类型金额在读取时,由于二进制无法准确存储92.10类型的数字,所以会产生精度误差,读取的结果是这样的。
结果:
第14行:交易金额 整数位数不大于9位,小数位数不大于3位;92.09999999999999
第16行:交易金额 整数位数不大于9位,小数位数不大于3位;92.09999999999999结单金额 整数位数不大于9位,小数位数不大于3位;92.09999999999999入账金额 整数位数不大于9位,小数位数不大于3位;92.09999999999999
第18行:交易金额 整数位数不大于9位,小数位数不大于3位;89.40000000000001结单金额 整数位数不大于9位,小数位数不大于3位;89.40000000000001入账金额 整数位数不大于9位,小数位数不大于3位;89.40000000000001
但是以上问题只在linux环境下会出现,在windows本机上测试并不会出现,也许和php版本有关,暂未探究。
第14行的交易金额是手动输入的92.10,这就排除了由于excel存储的数值本来就是超长小数的情况,问题可能是由于excel读取的问题或者php存储浮点数的问题,解决办法可以使用四舍五入来解决,但是请慎用。
2016-11-28 更新
经测试发现,当在服务器目录中放入下面代码,输出的数字并没有上述情况,怀疑是由于框架模板。
$item = array(
89.4,
92.1
);
var_dump($item);
可是在渲染html时传递的数组并没有这样的情况。
$this->render('GL0010',
array(
'a'=>array(
'a'=>92.1,
'b'=>89.4
)
)
);
页面显示如下:
array(2) { ["a"]=> float(92.1) ["b"]=> float(89.4) }
于是多次尝试问题原因,最后发现,在引入phpexcel之前,也就是执行下面代码之前,都是正常的。
include_once $url.'/protected/extensions/phpexcel/PHPExcel/IOFactory.php';
测试了,在这段代码之前定义空数组,然后在他下面使用角标重新定义空数组,使之其中含有92.1和89.4这两个数字,结果发现,不再报错,说明当引入phpexcel之后,对数组的创建产生了未知的影响,导致本来不存在精度问题的数字,出现异常。
最后这里的数字我使用number_format()函数解决。
$item['purchase_amount'] = number_format($item['purchase_amount'],3,'.',');
由于excel中的金额为保留2位小数,所以这里截取3位小数四舍五入可以保证金额精确,并且使千分位的字符为空,这样就得到了字符类型的数字金额,我的目的为导入数据库,至此任务完成。