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 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).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require brick/math
    

    Ensure PHP 8.2+ is used (or downgrade for older versions if needed).

  2. 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
    

Where to Look First

  • Documentation: Focus on the README for core concepts (immutability, factory methods, rounding modes).
  • API Reference: Check the source files for method signatures and edge cases.
  • Changelog: Review 0.17.x for breaking changes (e.g., BigDecimal::dividedBy() now requires $scale).

Implementation Patterns

Core Workflows

1. Precision-Critical Calculations

  • Use Case: Financial systems, cryptography, or scientific computing where floating-point inaccuracies are unacceptable.
  • Pattern:
    // 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));
    
  • Tip: Prefer BigDecimal for monetary values; use BigInteger for counts/IDs.

2. Chaining and Immutability

  • Use Case: Building complex expressions (e.g., parsing formulas from user input).
  • Pattern:
    $result = BigInteger::of(10)
        ->multipliedBy(2)
        ->plus(5)
        ->dividedBy(3); // 25/3 → RoundingNecessaryException (use rounding mode if needed)
    
  • Tip: Chain operations to avoid intermediate variables and ensure purity.

3. Rounding Modes

  • Use Case: Handling division with precision constraints (e.g., rounding to 2 decimal places for currency).
  • Pattern:
    use Brick\Math\RoundingMode;
    
    $rounded = BigDecimal::of('1.2345')
        ->dividedBy(3, 2, RoundingMode::HalfUp); // 0.41 (instead of 0.4166...)
    
  • Tip: Default to RoundingMode::HalfUp for financial rounding (bankers' rounding).

4. Type Conversion

  • Use Case: Integrating with legacy systems that use floats or strings.
  • Pattern:
    // Exact float representation (avoids rounding during conversion)
    $exact = BigDecimal::fromFloatExact(0.1); // 0.10000000000000000555...
    
    // Shortest decimal representation
    $shortest = BigDecimal::fromFloatShortest(0.1); // 0.1
    
  • Tip: Use fromFloatExact() for debugging; fromFloatShortest() for production.

5. Bitwise Operations

  • Use Case: Cryptography, hashing, or low-level data manipulation.
  • Pattern:
    $mask = BigInteger::of('0b1111'); // Binary literal
    $flag = BigInteger::of(1);
    $hasFlag = $mask->and($flag)->isZero(); // false
    
  • Tip: Combine with shiftedLeft()/shiftedRight() for bit manipulation.

6. Rational Numbers

  • Use Case: Exact fractions (e.g., 1/3 instead of 0.333...).
  • Pattern:
    $fraction = BigRational::of('2/3');
    $result = $fraction->dividedBy(4); // 1/6 (exact)
    
  • Tip: Useful for algorithms requiring exact arithmetic (e.g., computer algebra).

Integration Tips

  • Database: Store 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(),
        );
    }
    
  • Validation: Use NumberFormatException to catch malformed inputs.
    try {
        $number = BigDecimal::of($userInput);
    } catch (NumberFormatException $e) {
        return back()->withErrors(['input' => 'Invalid number format']);
    }
    
  • Testing: Mock BigDecimal for unit tests (e.g., using createMock()).
    $mock = $this->createMock(BigDecimal::class);
    $mock->method('toFloat')->willReturn(123.45);
    

Gotchas and Tips

Pitfalls

  1. Floating-Point Inputs:

    • Issue: BigDecimal::of(0.1) silently rounds to 0.10000000000000000555....
    • Fix: Use BigDecimal::of('0.1') or fromFloatExact()/fromFloatShortest().
    • Debugging: Compare BigDecimal::of('0.1')->toString() vs. BigDecimal::fromFloatExact(0.1)->toString().
  2. Division Without Scale:

    • Issue: BigDecimal::of(1)->dividedBy(3) throws RoundingNecessaryException (missing $scale).
    • Fix: Specify scale and rounding mode:
      $result = BigDecimal::of(1)->dividedBy(3, 2, RoundingMode::HalfUp); // 0.33
      
  3. Negative Modulus:

    • Issue: BigInteger::mod(-5) throws InvalidArgumentException (modulus must be positive).
    • Fix: Use abs() or validate inputs:
      $modulus = BigInteger::of($userInput)->abs();
      
  4. Zero Division:

    • Issue: BigInteger::of(1)->dividedBy(0) throws DivisionByZeroException.
    • Fix: Add explicit checks:
      if ($denominator->isZero()) {
          throw new \InvalidArgumentException('Denominator cannot be zero');
      }
      
  5. Precision Loss:

    • Issue: BigDecimal::of('1.0')->plus('0.1') may not equal 1.1 due to floating-point quirks.
    • Fix: Use exact fractions or strings:
      $exact = BigDecimal::of('1.0')->plus(BigDecimal::of('0.1')); // 1.1
      
  6. Serialization:

    • Issue: Serialized BigDecimal may lose precision if unserialized on a system without GMP/BCMath.
    • Fix: Store as strings or use jsonSerialize() for portability.
  7. Rounding Modes:

    • Issue: RoundingMode::Unnecessary throws RoundingNecessaryException if rounding is needed.
    • Fix: Use RoundingMode::Down/Up for truncation/ceiling.

Debugging Tips

  • Inspect Internals:
    $number = BigDecimal::of('1.2345');
    echo $number->getPrecision(); // 5
    echo
    
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope