Arbitrary Precision Maths Functions in PHP (BC Math)
Function Name | Function Description |
---|---|
bcadd() | Add two arbitrary precision numbers |
bccomp() | Compare two arbitrary precision numbers |
bcdiv() | Divide two arbitrary precision numbers |
bcmod() | Get modulus of an arbitrary precision number |
bcmul() | Multiply two arbitrary precision numbers |
bcpow() | Raise an arbitrary precision number to another |
bcpowmod() | Raise an arbitrary precision number to another, reduced by a specified modulus |
bcscale() | Set or get default scale parameter for all bc math functions |
bcsqrt() | Get the square root of an arbitrary precision number |
bcsub() | Subtract one arbitrary precision number from another |
PHP bcadd()
Function
PHP bcadd()
Usage
The PHP
function will sums bcadd()
left_operand
and right_operand
.
PHP bcadd()
Syntax
bcadd ( string $left_operand , string $right_operand [, int $scale = 0 ] ) : string
PHP bcadd()
Parameters
left_operand
— The left operand, as a string.right_operand
— The right operand, as a string.scale
— This optional parameter is used to set the number of digits after the decimal place in the result. If omitted, it will default to the scale set globally with thebcscale()
function, or fallback to 0 if this has not been set.
PHP bcadd()
Return Value
The PHP bcadd()
function returns the sum of the two operands, as a string.
PHP bcadd()
Working Examples
1. bcadd() example
<?php
$a = '1.234';
$b = '5';
echo bcadd($a, $b); // 6
echo bcadd($a, $b, 4); // 6.2340
?>
Additional Tips from Fellow Developers
Contributed By: Nitrogen
I made this to add an unlimited size of numbers together..
This could be useful for those without the BCMath extension.
It allows decimals, and optional $Scale parameter. If $Scale isn't specified, then it'll automatically adjust to show the correct number of decimals.
<?php
function Add($Num1,$Num2,$Scale=null) {
// check if they're valid positive numbers, extract the whole numbers and decimals
if(!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num1,$Tmp1)||
!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num2,$Tmp2)) return('0');
// this is where the result is stored
$Output=array();
// remove ending zeroes from decimals and remove point
$Dec1=isset($Tmp1[2])?rtrim(substr($Tmp1[2],1),'0'):'';
$Dec2=isset($Tmp2[2])?rtrim(substr($Tmp2[2],1),'0'):'';
// calculate the longest length of decimals
$DLen=max(strlen($Dec1),strlen($Dec2));
// if $Scale is null, automatically set it to the amount of decimal places for accuracy
if($Scale==null) $Scale=$DLen;
// remove leading zeroes and reverse the whole numbers, then append padded decimals on the end
$Num1=strrev(ltrim($Tmp1[1],'0').str_pad($Dec1,$DLen,'0'));
$Num2=strrev(ltrim($Tmp2[1],'0').str_pad($Dec2,$DLen,'0'));
// calculate the longest length we need to process
$MLen=max(strlen($Num1),strlen($Num2));
// pad the two numbers so they are of equal length (both equal to $MLen)
$Num1=str_pad($Num1,$MLen,'0');
$Num2=str_pad($Num2,$MLen,'0');
// process each digit, keep the ones, carry the tens (remainders)
for($i=0;$i<$MLen;$i++) {
$Sum=((int)$Num1{$i}+(int)$Num2{$i});
if(isset($Output[$i])) $Sum+=$Output[$i];
$Output[$i]=$Sum%10;
if($Sum>9) $Output[$i+1]=1;
}
// convert the array to string and reverse it
$Output=strrev(implode($Output));
// substring the decimal digits from the result, pad if necessary (if $Scale > amount of actual decimals)
// next, since actual zero values can cause a problem with the substring values, if so, just simply give '0'
// next, append the decimal value, if $Scale is defined, and return result
$Decimal=str_pad(substr($Output,-$DLen,$Scale),$Scale,'0');
$Output=(($MLen-$DLen<1)?'0':substr($Output,0,-$DLen));
$Output.=(($Scale>0)?".{$Decimal}":'');
return($Output);
}
$A="5650175242.508133742";
$B="308437806.831153821478770";
printf(" Add(%s,%s);\r\n// %s\r\n\r\n",$A,$B, Add($A,$B));
printf("BCAdd(%s,%s);\r\n// %s\r\n\r\n",$A,$B,BCAdd($A,$B));
/*
This will produce the following..
Add(5650175242.508133742,308437806.831153821478770);
// 5958613049.33928756347877
BCAdd(5650175242.508133742,308437806.831153821478770);
// 5958613049
*/
?>
It was a fun experience making, and thought I'd share it.
Enjoy,
Nitrogen.
PHP bccomp()
Function
PHP bccomp()
Usage
The PHP
function will give you the result as an integer.bccomp()
PHP bccomp()
Syntax
bccomp ( string $left_operand , string $right_operand [, int $scale = 0 ] ) : int
PHP bccomp()
Parameters
left_operand
— The left operand, as a string.right_operand
— The right operand, as a string.scale
— The optional scale parameter is used to set the number of digits after the decimal place which will be used in the comparison.
PHP bccomp()
Return Value
The PHP bccomp()
function returns 0 if the two operands are equal, 1 if the left_operand
is larger than the right_operand
, -1 otherwise.
PHP bccomp()
Working Examples
1. bccomp() example
<?php
echo bccomp('1', '2') . "\n"; // -1
echo bccomp('1.00001', '1', 3); // 0
echo bccomp('1.00001', '1', 5); // 1
?>
Additional Tips from Fellow Developers
Contributed By: Robert Lozyniak
Beware that negative zero does not compare equal to positive zero.
PHP bcdiv()
Function
PHP bcdiv()
Usage
The PHP
function will divides the bcdiv()
dividend
by the divisor
.
PHP bcdiv()
Syntax
bcdiv ( string $dividend , string $divisor [, int $scale = 0 ] ) : string
PHP bcdiv()
Parameters
dividend
— The dividend, as a string.divisor
— The divisor, as a string.scale
— This optional parameter is used to set the number of digits after the decimal place in the result. If omitted, it will default to the scale set globally with thebcscale()
function, or fallback to 0 if this has not been set.
PHP bcdiv()
Return Value
The PHP bcdiv()
function returns the result of the division as a string, or NULL
if divisor
is 0.
PHP bcdiv()
Working Examples
1. bcdiv() example
<?php
echo bcdiv('105', '6.55957', 3); // 16.007
?>
PHP bcmod()
Function
PHP bcmod()
Usage
The PHP
function will get modulus of an arbitrary precision number.bcmod()
PHP bcmod()
Syntax
bcmod ( string $dividend , string $divisor [, int $scale = 0 ] ) : string
PHP bcmod()
Parameters
dividend
— The dividend, as a string.divisor
— The divisor, as a string.
PHP bcmod()
Return Value
The PHP bcmod()
function returns the modulus as a string, or NULL
if divisor
is 0.
PHP bcmod()
Working Examples
1. bcmod() example
<?php
bcscale(0);
echo bcmod( '5', '3'); // 2
echo bcmod( '5', '-3'); // 2
echo bcmod('-5', '3'); // -2
echo bcmod('-5', '-3'); // -2
?>
2. bcmod() with decimals
<?php
bcscale(1);
echo bcmod('5.7', '1.3'); // 0.5 as of PHP 7.2.0; 0 previously
?>
Changelog for PHP bcmod() Function
7.2.0 — dividend
and divisor
are no longer truncated to integer, so now the behavior of bcmod()
follows fmod()
rather than the % operator.
7.2.0 — The scale
parameter was added.
PHP bcmul()
Function
PHP bcmul()
Usage
The PHP
function will multiply two arbitrary precision numbers.bcmul()
PHP bcmul()
Syntax
bcmul ( string $left_operand , string $right_operand [, int $scale = 0 ] ) : string
PHP bcmul()
Parameters
left_operand
— The left operand, as a string.right_operand
— The right operand, as a string.scale
— This optional parameter is used to set the number of digits after the decimal place in the result. If omitted, it will default to the scale set globally with thebcscale()
function, or fallback to 0 if this has not been set.
PHP bcmul()
Return Value
The PHP bcmul()
function returns the result as a string.
PHP bcmul()
Working Examples
1. bcmul() example
<?php
echo bcmul('1.34747474747', '35', 3); // 47.161
echo bcmul('2', '4'); // 8
?>
2. bcmul() scale example
<?php
echo bcmul('5', '2', 2); // prints "10", not "10.00"
?>
Changelog for PHP bcmul() Function
7.3.0 — bcmul()
now returns numbers with the requested scale. Formerly, the returned numbers may have omitted trailing decimal zeroes.
Important Points about PHP bcmul()
Function
Before PHP 7.3.0
bcmul()
may return a result with fewer digits after the decimal point than thescale
parameter would indicate. This only occurs when the result doesn't require all of the precision allowed by thescale
. For example:
<?php
echo bcmul('5', '2', 2); // prints "10", not "10.00"
?>
PHP bcpow()
Function
PHP bcpow()
Usage
The PHP
function will raise an arbitrary precision number to another.bcpow()
PHP bcpow()
Syntax
bcpow ( string $base , string $exponent [, int $scale = 0 ] ) : string
PHP bcpow()
Parameters
base
— The base, as a string.exponent
— The exponent, as a string. If the exponent is non-integral, it is truncated. The valid range of the exponent is platform specific, but is at least -2147483648 to 2147483647.scale
— This optional parameter is used to set the number of digits after the decimal place in the result. If omitted, it will default to the scale set globally with thebcscale()
function, or fallback to 0 if this has not been set.
PHP bcpow()
Return Value
The PHP bcpow()
function returns the result as a string.
PHP bcpow()
Working Examples
1. bcpow() example
<?php
echo bcpow('4.2', '3', 2); // 74.08
?>
2. bcpow() scale example
<?php
echo bcpow('5', '2', 2); // prints "25", not "25.00"
?>
Changelog for PHP bcpow() Function
7.3.0 — bcpow()
now returns numbers with the requested scale. Formerly, the returned numbers may have omitted trailing decimal zeroes.
Important Points about PHP bcpow()
Function
Before PHP 7.3.0
bcpow()
may return a result with fewer digits after the decimal point than thescale
parameter would indicate. This only occurs when the result doesn't require all of the precision allowed by thescale
. For example:
<?php
echo bcpow('5', '2', 2); // prints "25", not "25.00"
?>
PHP bcpowmod()
Function
PHP bcpowmod()
Usage
The PHP
function will raise an arbitrary precision number to another, reduced by a specified modulus.bcpowmod()
PHP bcpowmod()
Syntax
bcpowmod ( string $base , string $exponent , string $modulus [, int $scale = 0 ] ) : string
PHP bcpowmod()
Parameters
base
— The base, as an integral string (i.e. the scale has to be zero).exponent
— The exponent, as an non-negative, integral string (i.e. the scale has to be zero).modulus
— The modulus, as an integral string (i.e. the scale has to be zero).scale
— This optional parameter is used to set the number of digits after the decimal place in the result. If omitted, it will default to the scale set globally with thebcscale()
function, or fallback to 0 if this has not been set.
PHP bcpowmod()
Return Value
The PHP bcpowmod()
function returns the result as a string, or FALSE
if modulus
is 0 or exponent
is negative.
Important Points about PHP bcpowmod()
Function
Because this method uses the modulus operation, numbers which are not positive integers may give unexpected results.
PHP bcscale()
Function
PHP bcscale()
Usage
The PHP
function will set or get default scale parameter for all bc math functions.bcscale()
PHP bcscale()
Syntax
bcscale ( int $scale ) : int
bcscale ( void ) : int
PHP bcscale()
Parameters
scale
— The scale factor.
PHP bcscale()
Return Value
The PHP bcscale()
function returns the old scale when used as setter. Otherwise the current scale is returned.
PHP bcscale()
Working Examples
1. bcscale() example
<?php
// default scale : 3
bcscale(3);
echo bcdiv('105', '6.55957'); // 16.007
// this is the same without bcscale()
echo bcdiv('105', '6.55957', 3); // 16.007
?>
Changelog for PHP bcscale() Function
7.3.0 — bcscale()
can now be used to get the current scale factor; when used as setter, it now returns the old scale value. Formerly, scale
was mandatory, and bcscale()
always returned TRUE
.
Additional Tips from Fellow Developers
Contributed By: sicerwork
Executing bcsacle() will change the scale value of fpm.conf, not only the current process.
Contributed By: mwgamera
These functions DO NOT round off your values. No arbitrary precision libraries do it this way. It stops calculating after reaching scale of decimal places, which mean that your value is cut off after scale number of digits, not rounded. To do the rounding use something like this:
<?php
function bcround($number, $scale=0) {
$fix = "5";
for ($i=0;$i<$scale;$i++) $fix="0$fix";
$number = bcadd($number, "0.$fix", $scale+1);
return bcdiv($number, "1.0", $scale);
}
?>
PHP bcsqrt()
Function
PHP bcsqrt()
Usage
The PHP
function will get the square root of an arbitrary precision number.bcsqrt()
PHP bcsqrt()
Syntax
bcsqrt ( string $operand [, int $scale = 0 ] ) : string
PHP bcsqrt()
Parameters
operand
— The operand, as a string.scale
— This optional parameter is used to set the number of digits after the decimal place in the result. If omitted, it will default to the scale set globally with thebcscale()
function, or fallback to 0 if this has not been set.
PHP bcsqrt()
Return Value
The PHP bcsqrt()
function returns the square root as a string, or NULL
if operand
is negative.
PHP bcsqrt()
Working Examples
1. bcsqrt() example
<?php
echo bcsqrt('2', 3); // 1.414
?>
PHP bcsub()
Function
PHP bcsub()
Usage
The PHP
function will subtract one arbitrary precision number from another.bcsub()
PHP bcsub()
Syntax
bcsub ( string $left_operand , string $right_operand [, int $scale = 0 ] ) : string
PHP bcsub()
Parameters
left_operand
— The left operand, as a string.right_operand
— The right operand, as a string.scale
— This optional parameter is used to set the number of digits after the decimal place in the result. If omitted, it will default to the scale set globally with thebcscale()
function, or fallback to 0 if this has not been set.
PHP bcsub()
Return Value
The PHP bcsub()
function returns the result of the subtraction, as a string.
PHP bcsub()
Working Examples
1. bcsub() example
<?php
$a = '1.234';
$b = '5';
echo bcsub($a, $b); // -3
echo bcsub($a, $b, 4); // -3.7660
?>
Rate this post —