brick/math
Arbitrary-precision math for PHP. Work with big integers, decimals, and rational numbers via a clean OOP API. Optimized with GMP or BCMath when available, with automatic runtime selection. Requires PHP 8.2+ (older versions available).
Installation:
composer require brick/math
Ensure PHP 8.2+ is used (or downgrade for older versions if needed).
First Use Case:
use Brick\Math\BigInteger;
use Brick\Math\BigDecimal;
// Arbitrary-precision integer
$bigInt = BigInteger::of('9999999999999999999999999999999999999999999');
// Arbitrary-precision decimal
$bigDec = BigDecimal::of('9.99999999999999999999999999999999999999999999');
// Perform operations
echo $bigInt->plus(1); // 10000000000000000000000000000000000000000000
echo $bigDec->multipliedBy(2); // 19.99999999999999999999999999999999999999999998
BigDecimal::dividedBy() now requires $scale).// Avoid floats entirely; use strings or integers for input
$amount = BigDecimal::of('123.456789');
$taxRate = BigDecimal::of('0.075');
$total = $amount->plus($amount->multipliedBy($taxRate));
BigDecimal for monetary values; use BigInteger for counts/IDs.$result = BigInteger::of(10)
->multipliedBy(2)
->plus(5)
->dividedBy(3); // 25/3 → RoundingNecessaryException (use rounding mode if needed)
use Brick\Math\RoundingMode;
$rounded = BigDecimal::of('1.2345')
->dividedBy(3, 2, RoundingMode::HalfUp); // 0.41 (instead of 0.4166...)
RoundingMode::HalfUp for financial rounding (bankers' rounding).// Exact float representation (avoids rounding during conversion)
$exact = BigDecimal::fromFloatExact(0.1); // 0.10000000000000000555...
// Shortest decimal representation
$shortest = BigDecimal::fromFloatShortest(0.1); // 0.1
fromFloatExact() for debugging; fromFloatShortest() for production.$mask = BigInteger::of('0b1111'); // Binary literal
$flag = BigInteger::of(1);
$hasFlag = $mask->and($flag)->isZero(); // false
shiftedLeft()/shiftedRight() for bit manipulation.$fraction = BigRational::of('2/3');
$result = $fraction->dividedBy(4); // 1/6 (exact)
BigInteger/BigDecimal as strings or use Laravel’s Stringable cast.
use Brick\Math\BigDecimal;
use Illuminate\Database\Eloquent\Casts\Attribute;
public function total(): Attribute {
return Attribute::make(
get: fn ($value) => BigDecimal::of($value),
set: fn ($value) => $value->toString(),
);
}
NumberFormatException to catch malformed inputs.
try {
$number = BigDecimal::of($userInput);
} catch (NumberFormatException $e) {
return back()->withErrors(['input' => 'Invalid number format']);
}
BigDecimal for unit tests (e.g., using createMock()).
$mock = $this->createMock(BigDecimal::class);
$mock->method('toFloat')->willReturn(123.45);
Floating-Point Inputs:
BigDecimal::of(0.1) silently rounds to 0.10000000000000000555....BigDecimal::of('0.1') or fromFloatExact()/fromFloatShortest().BigDecimal::of('0.1')->toString() vs. BigDecimal::fromFloatExact(0.1)->toString().Division Without Scale:
BigDecimal::of(1)->dividedBy(3) throws RoundingNecessaryException (missing $scale).$result = BigDecimal::of(1)->dividedBy(3, 2, RoundingMode::HalfUp); // 0.33
Negative Modulus:
BigInteger::mod(-5) throws InvalidArgumentException (modulus must be positive).abs() or validate inputs:
$modulus = BigInteger::of($userInput)->abs();
Zero Division:
BigInteger::of(1)->dividedBy(0) throws DivisionByZeroException.if ($denominator->isZero()) {
throw new \InvalidArgumentException('Denominator cannot be zero');
}
Precision Loss:
BigDecimal::of('1.0')->plus('0.1') may not equal 1.1 due to floating-point quirks.$exact = BigDecimal::of('1.0')->plus(BigDecimal::of('0.1')); // 1.1
Serialization:
BigDecimal may lose precision if unserialized on a system without GMP/BCMath.jsonSerialize() for portability.Rounding Modes:
RoundingMode::Unnecessary throws RoundingNecessaryException if rounding is needed.RoundingMode::Down/Up for truncation/ceiling.$number = BigDecimal::of('1.2345');
echo $number->getPrecision(); // 5
echo
How can I help you explore Laravel packages today?