Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Math Laravel Package

brick/math

Arbitrary-precision math for PHP. Work with big integers, decimals and rationals reliably, with automatic acceleration via GMP or BCMath when available. PHP 8.2+ supported. Stable 0.x release cycles suitable for production.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require brick/math
    

    Ensure PHP ≥8.2 (or use compatible versions for older PHP).

  2. First Use Case: Handle arbitrary-precision arithmetic where native PHP types fail (e.g., financial calculations, cryptography, or large-scale scientific computations).

    use Brick\Math\BigDecimal;
    
    $amount = BigDecimal::of('1234567890.1234567890');
    $taxRate = BigDecimal::of('0.075');
    $total = $amount->multipliedBy($taxRate)->plus($amount);
    
  3. Key Entry Points:

    • BigInteger for whole numbers (e.g., IDs, hashes).
    • BigDecimal for precise decimals (e.g., money, measurements).
    • BigRational for fractions (e.g., ratios, probabilities).
    • RoundingMode for controlling precision (e.g., HalfUp, Down).
  4. Where to Look First:


Implementation Patterns

Core Workflows

  1. Precision-Critical Calculations:

    • Money/Financial Math:
      $price = BigDecimal::of('999999999999.99');
      $discount = BigDecimal::of('0.15'); // 15%
      $finalPrice = $price->multipliedBy($discount)->plus($price);
      
    • Cryptographic Hashes: Use BigInteger for large primes or modular arithmetic (e.g., RSA keys):
      $modulus = BigInteger::of('123456789012345678901234567890');
      $result = $modulus->modPow($exponent, $modulus);
      
  2. Data Migration/Validation:

    • Convert legacy float/double data to BigDecimal to avoid floating-point errors:
      $legacyFloat = 0.1 + 0.2; // 0.30000000000000004
      $safeDecimal = BigDecimal::fromFloatExact($legacyFloat);
      
  3. Chaining and Immutability:

    • Build complex expressions fluently:
      $result = BigDecimal::of('100')
          ->dividedBy('3', 2, RoundingMode::HalfUp)
          ->plus('5')
          ->multipliedBy('2');
      
  4. Rounding Strategies:

    • Use RoundingMode for consistent behavior (e.g., BankersRounding for accounting):
      $tax = BigDecimal::of('123.456')->dividedBy('4', 2, RoundingMode::Bankers);
      
  5. Interoperability:

    • Convert to/from strings or native types when needed:
      $string = $bigDecimal->toString(); // "123.456"
      $native = (string) $bigInteger;     // "99999999999999999999"
      

Integration Tips

  1. Dependency Injection:

    • Bind the factory methods in Laravel’s container:
      $this->app->bind(BigDecimal::class, fn() => BigDecimal::of('0'));
      
    • Use constructor injection for services requiring precision math.
  2. Form Requests:

    • Validate numeric inputs with BigDecimal:
      use Brick\Math\Exception\NumberFormatException;
      
      try {
          $amount = BigDecimal::of($request->input('amount'));
      } catch (NumberFormatException $e) {
          return back()->withErrors(['amount' => 'Invalid format']);
      }
      
  3. Database Storage:

    • Store BigInteger/BigDecimal as strings in DB (e.g., BIGINT for hashes, TEXT for decimals).
    • Use accessors/mutators for seamless conversion:
      public function getAmountAttribute($value) {
          return BigDecimal::of($value);
      }
      
  4. Testing:

    • Mock BigDecimal for isolated tests:
      $this->partialMock(BigDecimal::class, ['dividedBy'])
           ->method('dividedBy')
           ->willReturn(BigDecimal::of('1.5'));
      
  5. Performance:

    • Prefer GMP/BCMath extensions for heavy computations (auto-selected by the library).
    • Cache repeated calculations (e.g., tax rates) as static BigDecimal instances.

Gotchas and Tips

Pitfalls

  1. Floating-Point Traps:

    • Avoid float inputs: BigDecimal::of(0.1) throws NumberFormatException. Use strings or fromFloatExact():
      // ❌ Fails
      BigDecimal::of(0.1);
      
      // ✅ Works
      BigDecimal::of('0.1');
      // or
      BigDecimal::fromFloatExact(0.1);
      
  2. Rounding Modes:

    • Default behavior changed in 0.15.0: dividedBy() now requires explicit scale and RoundingMode. Old code:
      // ❌ Breaks in 0.15+
      $result = $decimal->dividedBy('3');
      
      New code:
      // ✅ Required
      $result = $decimal->dividedBy('3', 2, RoundingMode::HalfUp);
      
  3. BigInteger Modulo:

    • Semantics changed in 0.15.0: mod() now uses Euclidean modulo (always non-negative). Old code:
      // ❌ May return negative
      $modulus = BigInteger::of(-5);
      $result = $number->mod($modulus);
      
      New code:
      // ✅ Throws InvalidArgumentException
      $result = $number->mod($modulus); // Fails if $modulus ≤ 0
      
  4. BigRational Simplification:

    • Always reduced: BigRational::of('4/6') returns 2/3 (no simplified() method).
  5. Serialization:

    • Extension-independent: Serialized objects work across machines with mismatched PHP extensions (e.g., GMP vs. pure PHP).
  6. Bitwise Operations:

    • Only for BigInteger: BigDecimal/BigRational lack bitwise methods.

Debugging Tips

  1. Exception Handling:

    • Catch MathException broadly or specific exceptions (e.g., RoundingNecessaryException) for granular control.
    • Use try-catch for user-facing errors (e.g., invalid input):
      try {
          $decimal = BigDecimal::of($userInput);
      } catch (NumberFormatException $e) {
          report($e);
          return back()->withErrors(['input' => 'Invalid number']);
      }
      
  2. Precision Debugging:

    • Check scale/rounding with:
      $decimal->getScale(); // Returns current decimal places
      $decimal->strippedOfTrailingZeros()->toString(); // Normalized string
      
  3. Performance Bottlenecks:

    • Profile with/without GMP/BCMath:
      // Force pure PHP (for testing)
      putenv('BRICK_MATH_CALCULATOR=php');
      
  4. Changelog Gotchas:

    • 0.16.0: BigDecimal::getIntegralPart() now returns BigInteger (was int).
    • 0.17.0: BigDecimal::hasNonZeroFractionalPart() removed; use ! $number->getFractionalPart()->isZero().

Extension Points

  1. Custom Calculators:

    • Implement Brick\Math\Calculator\CalculatorInterface for domain-specific optimizations (e.g., GPU acceleration).
  2. PHPStan Integration:

    • Add simPod/phpstan-brick-math for static analysis:
      composer require --dev simpod/phpstan-brick-math
      
    • Configure in `phpstan.ne
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport