# How TypePHP Handles High-Precision Numeric Types: BigInt, Decimal, and BigFloat

> Discover how TypePHP's BigInt, Decimal, and BigFloat classes deliver arbitrary-precision arithmetic using GMP and BCMath, preventing precision loss with strict compile-time checks.

- Repository: [Swoole Project/typephp](https://github.com/swoole/typephp)
- Tags: deep-dive
- Published: 2026-08-30

---

**TypePHP provides arbitrary-precision arithmetic through three specialized classes—`\TypePHP\BigInt`, `\TypePHP\BigFloat`, and `\TypePHP\Decimal`—backed by GMP and BCMath extensions, while enforcing strict compile-time rules to prevent accidental precision loss.**

TypePHP extends PHP with native support for high-precision numeric types critical for financial calculations and scientific computing. In the `swoole/typephp` repository, these types are implemented as immutable value objects accessible through helper functions defined in [`src/polyfills.php`](https://github.com/swoole/typephp/blob/main/src/polyfills.php), offering unlimited precision without sacrificing type safety.

## The Three High-Precision Numeric Classes

TypePHP introduces three distinct classes to handle different precision requirements, each residing in the `\TypePHP` namespace and instantiated via global helper functions.

### BigInt for Arbitrary-Length Integers

The **BigInt** type represents integers of unlimited magnitude, bypassing PHP's native 32-bit or 64-bit integer limits. When the GMP extension is available, operations use native GMP functions; otherwise, a pure-PHP fallback implementation ensures portability.

```php
$largePrime = std::bigInt('123456789012345678901234567890');
$factorial = $largePrime->mul(std::bigInt('2')); // Unlimited precision multiplication

```

### BigFloat for High-Precision Floating-Point

**BigFloat** handles floating-point numbers with arbitrary precision, avoiding the rounding errors inherent in IEEE 754 doubles. Like BigInt, it prefers the GMP extension but falls back to BCMath or pure-PHP implementations depending on the environment.

```php
$pi = std::bigFloat('3.141592653589793238462643383279');
$circumference = $pi->mul(std::bigFloat('2')); // Maintains full precision throughout

```

### Decimal for Fixed-Point Arithmetic

The **Decimal** type provides exact fixed-point arithmetic essential for monetary calculations, using BCMath under the hood. Unlike floating-point types, Decimal maintains a specific scale (number of decimal places) to ensure deterministic rounding behavior.

```php
$price = std::decimal('99.99', 2); // Scale of 2 for currency
$total = $price->mul(std::decimal('1.15')); // 114.9885 with exact precision

```

## Internal Implementation and Backing Libraries

The high-precision types in TypePHP leverage PHP's mathematical extensions through a unified abstraction layer. In [`src/polyfills.php`](https://github.com/swoole/typephp/blob/main/src/polyfills.php), the helper functions `std::bigInt()`, `std::bigFloat()`, and `std::decimal()` serve as thin wrappers that accept scalar values (strings, integers, or floats) and return immutable instances of their respective classes.

These classes implement PHP's magic methods—such as `__add`, `__sub`, `__mul`, and `__div`—to support natural arithmetic syntax while delegating actual calculations to GMP or BCMath functions. This architecture ensures that `swoole/typephp` delivers native performance when extensions are available while maintaining functionality in restricted environments.

## Compile-Time Type Safety Rules

TypePHP enforces strict compatibility between high-precision types at compile time to prevent subtle precision bugs. The parser actively rejects code that would implicitly mix incompatible numeric types.

According to the source code in [`src/Parser/BinaryOpTrait.php`](https://github.com/swoole/typephp/blob/main/src/Parser/BinaryOpTrait.php) (line 65), mixing a **BigInt** with a **Decimal** or **BigFloat** in a binary operation triggers a compile-time error with the message: *"Cannot mix BigInt and Decimal implicitly. Use std::decimal() or std::bigInt() to convert explicitly."*

Key compatibility constraints include:

- **Same-type operations** between two BigInt, two BigFloat, or two Decimal values are permitted and execute with underlying library precision.
- **Implicit scalar conversion** is allowed only when a native PHP scalar can be represented exactly in the target type (e.g., integer literals to BigInt).
- **Cross-type arithmetic** requires explicit conversion via `toBigInt()`, `toDecimal()`, or constructor helpers to ensure developers acknowledge potential precision changes.

Runtime compatibility checks are further implemented in [`src/TypeSystem/NativeTypeCompatibilityTrait.php`](https://github.com/swoole/typephp/blob/main/src/TypeSystem/NativeTypeCompatibilityTrait.php), providing additional guards during execution.

## Practical Usage Examples

The following patterns demonstrate creation, arithmetic operations, and safe type conversion between high-precision numeric types in TypePHP.

```php
<?php
// Creation with explicit string literals to avoid floating-point contamination
$bigInt   = std::bigInt('123456789012345678901234567890');
$bigFloat = std::bigFloat('3.141592653589793238462643383279');
$decimal  = std::decimal('99.99');

// Arithmetic maintains precision automatically
$sum      = $bigInt->add(std::bigInt('1'));
$product  = $bigFloat->mul(std::bigFloat('2'));
$price    = $decimal->mul(std::decimal('1.15'));

// Explicit conversion required when mixing types
// $illegal = $bigInt + $decimal; // Compile-time error

// Safe conversion paths
$intFromDecimal = $decimal->toBigInt();     // Truncates to 99
$decimalFromInt = $bigInt->toDecimal(0);   // Converts with scale 0

// Interoperability with native scalars
$mixedSum  = $bigInt->add(42);              // Native int auto-converted
$mixedFloat = $bigFloat->add(0.5);         // Native float accepted by BigFloat

```

Reference implementations and test cases are available in [`examples/high-precision.php`](https://github.com/swoole/typephp/blob/main/examples/high-precision.php) and [`phpunit/code/big-numeric/mixed-big-comparison.php`](https://github.com/swoole/typephp/blob/main/phpunit/code/big-numeric/mixed-big-comparison.php), which validate comparison semantics and edge cases for these numeric types.

## Summary

- TypePHP implements three high-precision numeric types—**BigInt**, **BigFloat**, and **Decimal**—through the `\TypePHP` namespace, accessible via `std::bigInt()`, `std::bigFloat()`, and `std::decimal()` helpers defined in [`src/polyfills.php`](https://github.com/swoole/typephp/blob/main/src/polyfills.php).
- **BigInt** and **BigFloat** prefer the GMP extension with pure-PHP fallbacks, while **Decimal** relies on BCMath for fixed-point arithmetic.
- The compiler prevents implicit mixing of BigInt with Decimal or BigFloat, throwing errors from [`src/Parser/BinaryOpTrait.php`](https://github.com/swoole/typephp/blob/main/src/Parser/BinaryOpTrait.php) unless explicit conversion methods are used.
- All three types support natural arithmetic operators through magic methods while maintaining arbitrary precision throughout calculations.

## Frequently Asked Questions

### What happens when BigInt and Decimal are mixed in the same expression?

TypePHP emits a compile-time error before execution occurs. According to the parser logic in [`src/Parser/BinaryOpTrait.php`](https://github.com/swoole/typephp/blob/main/src/Parser/BinaryOpTrait.php), the compiler detects the type mismatch and requires explicit conversion using `toDecimal()` or `toBigInt()` methods to ensure the developer intentionally accepts any precision loss from the conversion.

### Does TypePHP require the GMP extension to be installed?

No, though GMP is preferred for performance. The BigInt and BigFloat implementations include pure-PHP fallback logic when GMP is unavailable. However, the Decimal type specifically requires BCMath for its fixed-point operations, which is typically available in standard PHP builds.

### How do I control the number of decimal places in Decimal calculations?

Pass the desired scale (number of fractional digits) as the second argument to `std::decimal()`. For example, `std::decimal('99.99', 4)` creates a Decimal with four decimal places. Arithmetic operations preserve this scale, and rounding behavior follows BCMath's fixed-point semantics to ensure deterministic financial calculations.

### Can high-precision types be compared directly with native PHP integers?

Yes, TypePHP permits direct comparison between high-precision types and native PHP scalars when the scalar can be represented exactly. Runtime compatibility checks in [`src/TypeSystem/NativeTypeCompatibilityTrait.php`](https://github.com/swoole/typephp/blob/main/src/TypeSystem/NativeTypeCompatibilityTrait.php) handle these comparisons, though explicit conversion is recommended for absolute type safety in complex expressions.