注意,负零与正零不相等。
(PHP 4, PHP 5, PHP 7, PHP 8)
bccomp — 比较两个任意精度的数字
num1
左操作数,以字符串形式表示。
num2
右操作数,以字符串形式表示。
scale
可选的 scale
参数用于设置比较中使用的十进制小数位数。
如果两个操作数相等,则返回 0;如果 num1
大于 num2
,则返回 1;否则返回 -1。
版本 | 描述 |
---|---|
8.0.0 |
scale 现在可为空。 |
示例 #1 bccomp() 示例
<?php
echo bccomp('1', '2') . "\n"; // -1
echo bccomp('1.00001', '1', 3); // 0
echo bccomp('1.00001', '1', 5); // 1
?>
改进最初由 frank at booksku dot com 编写的 bcmax() 和 bcmin() 函数。
<?php
function bcmax() {
$args = func_get_args();
if (count($args)==0) return false;
$max = $args[0];
foreach($args as $value) {
if (bccomp($value, $max)==1) {
$max = $value;
}
}
return $max;
}
function bcmin() {
$args = func_get_args();
if (count($args)==0) return false;
$min = $args[0];
foreach($args as $value) {
if (bccomp($min, $value)==1) {
$min = $value;
}
}
return $min;
}
?>
我用 bccomp() 粗略地拼凑了 min() 和 max() 函数。虽然 min() 和 max() 只能接受任意数量的参数(例如 max(1, 5, 1235, 12934, 66)),但 bccomp 只能接受 2 个参数。
注意,这没有考虑 $scale。
<?php
function bcmax() {
$max = null;
foreach(func_get_args() as $value) {
if ($max == null) {
$max = $value;
} else if (bccomp($max, $value) < 0) {
$max = $value;
}
}
return $max;
}
function bcmin() {
$min = null;
foreach(func_get_args() as $value) {
if ($min == null) {
$min = $value;
} else if (bccomp($min, $value) > 0) {
$min = $value;
}
}
return $min;
}
?>
我创建了这个来比较无限大小的数字。
这对那些没有 BCMath 扩展的人来说可能很有用。
它允许小数,以及可选的 $Scale 参数。如果未指定 $Scale,则它将自动调整为正确的十进制小数位数进行比较。
<?php
function Comp($Num1,$Num2,$Scale=null) {
// 检查它们是否为有效的正数,提取整数和小数部分
if(!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num1,$Tmp1)||
!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num2,$Tmp2)) return('0');
// 从整数部分去除前导零
$Num1=ltrim($Tmp1[1],'0');
$Num2=ltrim($Tmp2[1],'0');
// 首先,我们可以直接检查数字的长度,这可以帮助节省处理时间
// 如果 $Num1 比 $Num2 长,返回 1.. 反之亦然,在下一步中。
if(strlen($Num1)>strlen($Num2)) return(1);
else {
if(strlen($Num1)<strlen($Num2)) return(-1);
// 如果两个数字的长度相同,我们逐位检查
else {
// 从小数部分去除尾部零并去除小数点
$Dec1=isset($Tmp1[2])?rtrim(substr($Tmp1[2],1),'0'):'';
$Dec2=isset($Tmp2[2])?rtrim(substr($Tmp2[2],1),'0'):'';
// 如果用户定义了 $Scale,则确保我们只使用它
if($Scale!=null) {
$Dec1=substr($Dec1,0,$Scale);
$Dec2=substr($Dec2,0,$Scale);
}
// 计算小数部分的最长长度
$DLen=max(strlen($Dec1),strlen($Dec2));
// 将填充后的的小数部分附加到整数部分的末尾
$Num1.=str_pad($Dec1,$DLen,'0');
$Num2.=str_pad($Dec2,$DLen,'0');
// 逐位检查,如果它们有差异,返回 1 或 -1(大于/小于)
for($i=0;$i<strlen($Num1);$i++) {
if((int)$Num1{$i}>(int)$Num2{$i}) return(1);
else
if((int)$Num1{$i}<(int)$Num2{$i}) return(-1);
}
// 如果两个数字没有差异(它们相同).. 返回 0
return(0);
}
}
}
$A="10.50002";
$B="10.50001";
printf(" Comp(%s,%s); // %s\r\n",$A,$B, Comp($A,$B));
printf("BCComp(%s,%s); // %s\r\n",$A,$B,BCComp($A,$B));
/*
Comp(10.50002,10.50001); // 1
BCComp(10.50002,10.50001); // 0 (BCComp 默认的小数位数为 0,除非指定)
*/
?>
我试图让它像 BCComp 一样工作..
唯一的区别是我会默认比较小数.. 而 BCComp 不会..
.. 除非,当然,您指定要包含在处理过程中的小数位数。
享受,
氮气。
请注意,上面的函数违背了 BCMath 函数的用途,因为它使用了“传统”的 < 运算符。
相反,它应该:
<?php
function my_bccomp_zero($amount, $scale)
{
if (@$amount{0}=="-")
{
return bccomp($amount, '-0.0', $scale);
}
else
{
return bccomp($amount, '0.0', $scale);
}
}
?>
您可以将此函数与 version_compare() 包裹在一起,以支持运算符并获得更友好的(布尔)返回值。
<?php
function _bccomp($a, $b, $operator = '=')
{
return version_compare(bccomp($a, $b), 0, $operator);
}
var_dump(_bccomp(5, 3, '>=')); // true
?>
仍然适用于任意长度的数字。
bccomp - 默认情况下不会比较超过 16 个字符。
$number = '-4.444444444444444444444444444444444444444444445';
$precision = 16;
var_dump(bccomp(bcadd($number, '0', $precision), bcadd($number, '0', $precision+1)));
// 在 PHP 5.3 中输出 0
使用 strcomp