Project status & release process
While this library is still under development, it is well tested and considered stable enough to use in production environments.
The current releases are numbered 0.x.y
. When a non-breaking change is introduced (adding new methods, optimizing
existing code, etc.), y
is incremented.
When a breaking change is introduced, a new 0.x
version cycle is always started.
It is therefore safe to lock your project to a given release cycle, such as ^0.12
.
If you need to upgrade to a newer release cycle, check the release history
for a list of changes introduced by each further 0.x.0
version.
Package contents
This library provides the following public classes in the Brick\Math
namespace:
- BigNumber: base class for
BigInteger
,BigDecimal
andBigRational
- BigInteger: represents an arbitrary-precision integer number.
- BigDecimal: represents an arbitrary-precision decimal number.
- BigRational: represents an arbitrary-precision rational number (fraction).
- RoundingMode: enum representing all available rounding modes.
And the following exceptions in the Brick\Math\Exception
namespace:
- MathException: base class for all exceptions
- DivisionByZeroException: thrown when a division by zero occurs
- IntegerOverflowException: thrown when attempting to convert a too large
BigInteger
toint
- NumberFormatException: thrown when parsing a number string in an invalid format
- RoundingNecessaryException: thrown when the result of the operation cannot be represented without explicit rounding
- NegativeNumberException: thrown when attempting to calculate the square root of a negative number
Overview
Immutability & chaining
The BigInteger
, BigDecimal
and BigRational
classes are immutable: their value never changes,
so that they can be safely passed around. All methods that return a BigInteger
, BigDecimal
or BigRational
return a new object, leaving the original object unaffected:
$ten = BigInteger::of(10);
echo $ten->plus(5); // 15
echo $ten->multipliedBy(3); // 30
The methods can be chained for better readability:
echo BigInteger::of(10)->plus(5)->multipliedBy(3); // 45
Parameter types
All methods that accept a number: plus()
, minus()
, multipliedBy()
, etc. accept the same types as of()
.
For example, given the following number:
$integer = BigInteger::of(123);
The following lines are equivalent:
$integer->multipliedBy(123);
$integer->multipliedBy('123');
$integer->multipliedBy($integer);
Just like of()
, other types of BigNumber
are acceptable, as long as they can be safely converted to the current type:
echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.0')); // 4
echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.5')); // RoundingNecessaryException
echo BigDecimal::of(2.5)->multipliedBy(BigInteger::of(2)); // 5.0
Division & rounding
BigInteger
By default, dividing a BigInteger
returns the exact result of the division, or throws an exception if the remainder
of the division is not zero:
echo BigInteger::of(999)->dividedBy(3); // 333
echo BigInteger::of(1000)->dividedBy(3); // RoundingNecessaryException
You can pass an optional rounding mode to round the result, if necessary:
echo BigInteger::of(1000)->dividedBy(3, RoundingMode::DOWN); // 333
echo BigInteger::of(1000)->dividedBy(3, RoundingMode::UP); // 334
If you’re into quotients and remainders, there are methods for this, too:
echo BigInteger::of(1000)->quotient(3); // 333
echo BigInteger::of(1000)->remainder(3); // 1
You can even get both at the same time:
[$quotient, $remainder] = BigInteger::of(1000)->quotientAndRemainder(3);
BigDecimal
Dividing a BigDecimal
always requires a scale to be specified. If the exact result of the division does not fit in
the given scale, a rounding mode must be provided.
echo BigDecimal::of(1)->dividedBy('8', 3); // 0.125
echo BigDecimal::of(1)->dividedBy('8', 2); // RoundingNecessaryException
echo BigDecimal::of(1)->dividedBy('8', 2, RoundingMode::HALF_DOWN); // 0.12
echo BigDecimal::of(1)->dividedBy('8', 2, RoundingMode::HALF_UP); // 0.13
If you know that the division yields a finite number of decimals places, you can use exactlyDividedBy()
, which will
automatically compute the required scale to fit the result, or throw an exception if the division yields an infinite
repeating decimal:
echo BigDecimal::of(1)->exactlyDividedBy(256); // 0.00390625
echo BigDecimal::of(1)->exactlyDividedBy(11); // RoundingNecessaryException
BigRational
The result of the division of a BigRational
can always be represented exactly:
echo BigRational::of('123/456')->dividedBy('7'); // 123/3192
echo BigRational::of('123/456')->dividedBy('9/8'); // 984/4104