Skip to content

Refactor to use BcMath\Number for internal storage#3

Open
barryvdh-bot wants to merge 9 commits intofruitcake:mainfrom
barryvdh-bot:feature/bcmath-number
Open

Refactor to use BcMath\Number for internal storage#3
barryvdh-bot wants to merge 9 commits intofruitcake:mainfrom
barryvdh-bot:feature/bcmath-number

Conversation

@barryvdh-bot
Copy link

Summary

This PR refactors the Decimal class to use PHP 8.4's BcMath\Number class for internal value storage instead of unit values with precision multipliers.

Breaking Changes

  • Minimum PHP version is now 8.4 (required for BcMath\Number class)
  • Added ext-bcmath as a required extension
  • PHPUnit upgraded to version 11

Changes

Internal Storage

  • Values are now stored as BcMath\Number instances instead of string unit values
  • Internal calculations use scale 20 for higher precision
  • Precision parameter now only affects output formatting, not internal storage

New Features

  • getValue() method to access the internal BcMath\Number instance
  • toString() now accepts an optional precision parameter for custom output precision

Improvements

  • Better precision for complex calculations (e.g., divide then multiply no longer loses precision)
  • Support for very large and very small numbers with arbitrary precision

Backwards Compatibility

The public API remains the same:

  • getUnitValue() still works for backwards compatibility
  • All existing tests pass
  • Arithmetic and comparison methods work identically

Tests

Added new tests for:

  • High precision division
  • Internal precision higher than display precision
  • Very large numbers
  • Very small numbers with high precision

This PR was created by Borry 🤖

BREAKING CHANGES:
- Minimum PHP version is now 8.4 (for BcMath\Number class)
- Added ext-bcmath as required extension

Changes:
- Internal value storage now uses BcMath\Number instead of unit values
- Internal calculations use scale 20 for higher precision
- Added getValue() method to access internal BcMath\Number
- toString() now accepts optional precision parameter
- Updated tests for new implementation
- Added tests for high precision scenarios

This provides better precision for complex calculations while
maintaining backwards compatibility with the existing API.
- Update run-tests.yml to only test PHP 8.4 and 8.5
- Update coverage.yml to use PHP 8.4
- Update phpunit-matcher.yml to use PHP 8.4
- Add bcmath and intl extensions to CI
- Update to actions/checkout@v4
- Remove deprecated --no-suggest flag
- isZero() now checks if value rounds to zero at display precision
- isPositive/isNegative respect the isZero check
- toNumber() handles very small floats (< 1e-14) as zero to avoid scientific notation
- Use number_format instead of sprintf to avoid scientific notation issues
Pre-round floats to 10 decimal places to correct floating-point
representation errors before converting to BcMath\Number.

e.g., 1.345 in float is ~1.34499999... which should round to 1.35,
not 1.34
- testConstructWithNumber: Number in constructor
- testArithmeticWithNumber: Number in add/sub/multiply/divide
- testComparisonWithNumber: Number in comparisons
Fixes:
- All comparison methods now use display precision for consistency
- Division by zero now throws DivisionByZeroError

New features:
- compare() method returning -1, 0, 1
- abs() method for absolute value
- negate() method to change sign
- parseLocale() accepts optional locale parameter (null = system default)
- Support for negative precision in toString()

Tests added for all new functionality
- Default locale back to 'nl_NL' for backwards compatibility
- Fix testComparisonConsistency: 1.006 rounds to 1.01, not 1.00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant