Skip to content

Commit d8c96c1

Browse files
committed
Update README
[skip CI]
1 parent a4dee0c commit d8c96c1

File tree

1 file changed

+185
-50
lines changed

1 file changed

+185
-50
lines changed

README.md

Lines changed: 185 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Brick\Math
1+
# Brick\Math
22

33
<img src="https://raw.githubusercontent.com/brick/brick/master/logo.png" alt="" align="left" height="64">
44

@@ -10,6 +10,18 @@ A PHP library to work with arbitrary precision numbers.
1010
[![Total Downloads](https://poser.pugx.org/brick/math/downloads)](https://packagist.org/packages/brick/math)
1111
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT)
1212

13+
## Introduction
14+
15+
This library provides immutable classes to work with three types of numbers:
16+
17+
- `BigInteger` — an integer number such as `123`
18+
- `BigDecimal` — a decimal number such as `1.23`
19+
- `BigRational` — a fraction such as `2/3` — always reduced to lowest terms, e.g. `2/6` becomes `1/3`
20+
21+
It automatically uses GMP or BCMath when available, and falls back to a pure-PHP implementation otherwise.
22+
23+
All classes work with a virtually **unlimited number of digits**, and are limited only by available memory and CPU time.
24+
1325
### Installation
1426

1527
This library is installable via [Composer](https://getcomposer.org/):
@@ -22,42 +34,29 @@ composer require brick/math
2234

2335
This library requires PHP 8.2 or later.
2436

25-
For PHP 8.1 compatibility, you can use version `0.13`. For PHP 8.0, you can use version `0.11`. For PHP 7.4, you can use version `0.10`. For PHP 7.1, 7.2 & 7.3, you can use version `0.9`. Note that [PHP versions < 8.1 are EOL](http://php.net/supported-versions.php) and not supported anymore. If you're still using one of these PHP versions, you should consider upgrading as soon as possible.
26-
2737
Although the library can work seamlessly on any PHP installation, it is highly recommended that you install the
2838
[GMP](http://php.net/manual/en/book.gmp.php) or [BCMath](http://php.net/manual/en/book.bc.php) extension
2939
to speed up calculations. The fastest available calculator implementation will be automatically selected at runtime.
3040

31-
### Project status & release process
32-
33-
While this library is still under development, it is well tested and considered stable enough to use in production
34-
environments.
35-
36-
The current releases are numbered `0.x.y`. When a non-breaking change is introduced (adding new methods, optimizing
37-
existing code, etc.), `y` is incremented.
38-
39-
**When a breaking change is introduced, a new `0.x` version cycle is always started.**
40-
41-
It is therefore safe to lock your project to a given release cycle, such as `^0.14`.
42-
43-
If you need to upgrade to a newer release cycle, check the [release history](https://github.com/brick/math/releases)
44-
for a list of changes introduced by each further `0.x.0` version.
41+
## Number classes
4542

46-
### Package contents
43+
The three number classes all extend the same `BigNumber` class:
4744

48-
This library provides the following public classes in the `Brick\Math` namespace:
49-
50-
- [BigNumber](https://github.com/brick/math/blob/0.14.7/src/BigNumber.php): base class for `BigInteger`, `BigDecimal` and `BigRational`
51-
- [BigInteger](https://github.com/brick/math/blob/0.14.7/src/BigInteger.php): represents an arbitrary-precision integer number.
52-
- [BigDecimal](https://github.com/brick/math/blob/0.14.7/src/BigDecimal.php): represents an arbitrary-precision decimal number.
53-
- [BigRational](https://github.com/brick/math/blob/0.14.7/src/BigRational.php): represents an arbitrary-precision rational number (fraction), always reduced to lowest terms.
54-
- [RoundingMode](https://github.com/brick/math/blob/0.14.7/src/RoundingMode.php): enum representing all available rounding modes.
45+
```
46+
Brick\Math\BigNumber
47+
├── Brick\Math\BigInteger
48+
├── Brick\Math\BigDecimal
49+
└── Brick\Math\BigRational
50+
```
5551

56-
And [exceptions](#exceptions) in the `Brick\Math\Exception` namespace.
52+
`BigNumber` is an abstract class that defines the common behaviour of all number classes:
5753

58-
### Overview
54+
- `of()` — to obtain an instance
55+
- sign methods: `isZero()`, `isPositive()`, etc.
56+
- comparison methods: `isEqualTo()`, `isGreaterThan()`, etc.
57+
- `min()`, `max()`, `sum()`, `toString()`, etc.
5958

60-
#### Instantiation
59+
## Instantiation
6160

6261
The constructors of the classes are not public, you must use a factory method to obtain an instance.
6362

@@ -89,7 +88,7 @@ BigDecimal::of('1/8'); // 0.125
8988
BigDecimal::of('1/3'); // RoundingNecessaryException
9089

9190
BigRational::of('1.1'); // 11/10
92-
BigRational::of('1.15'); // 23/20 (reduced to lowest terms)
91+
BigRational::of('1.15'); // 23/20
9392
```
9493

9594
> [!NOTE]
@@ -107,7 +106,7 @@ BigRational::of('1.15'); // 23/20 (reduced to lowest terms)
107106
> BigDecimal::of((string) $float);
108107
> ```
109108
110-
#### Immutability & chaining
109+
## Immutability & chaining
111110
112111
The `BigInteger`, `BigDecimal` and `BigRational` classes are immutable: their value never changes,
113112
so that they can be safely passed around. All methods that return a `BigInteger`, `BigDecimal` or `BigRational`
@@ -126,7 +125,7 @@ The methods can be chained for better readability:
126125
echo BigInteger::of(10)->plus(5)->multipliedBy(3); // 45
127126
```
128127

129-
#### Parameter types
128+
## Parameter types
130129

131130
All methods that accept a number: `plus()`, `minus()`, `multipliedBy()`, etc. accept the same types as `of()`.
132131
For example, given the following number:
@@ -151,9 +150,43 @@ echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.5')); // RoundingNecessar
151150
echo BigDecimal::of(2.5)->multipliedBy(BigInteger::of(2)); // 5.0
152151
```
153152

154-
#### Division & rounding
153+
## Rounding
154+
155+
Unless documented otherwise, all methods either return an exact result or throw an exception if the result is not exact.
156+
This is typically configurable through an optional `RoundingMode` parameter:
157+
158+
| Rounding mode | Description |
159+
|-----------------------------|---------------------------------------------------------------|
160+
| `RoundingMode::Unnecessary` | Requires an exact result; throws if rounding would be needed. |
161+
| `RoundingMode::Up` | Rounds away from zero. |
162+
| `RoundingMode::Down` | Rounds toward zero. |
163+
| `RoundingMode::Ceiling` | Rounds toward positive infinity. |
164+
| `RoundingMode::Floor` | Rounds toward negative infinity. |
165+
| `RoundingMode::HalfUp` | Rounds to nearest; ties away from zero. |
166+
| `RoundingMode::HalfDown` | Rounds to nearest; ties toward zero. |
167+
| `RoundingMode::HalfCeiling` | Rounds to nearest; ties toward positive infinity. |
168+
| `RoundingMode::HalfFloor` | Rounds to nearest; ties toward negative infinity. |
169+
| `RoundingMode::HalfEven` | Rounds to nearest; ties to the even neighbor. |
170+
171+
See the next section for examples of `RoundingMode` in action.
172+
173+
## Arithmetic operations
174+
175+
### Addition, subtraction and multiplication
176+
177+
These operations are straightforward on all number classes:
178+
179+
```php
180+
echo BigInteger::of(1)->plus(2)->multipliedBy(3); // 9
181+
echo BigDecimal::of('1.2')->plus(BigDecimal::of('3.4'))->multipliedBy('5.6'); // 25.76
182+
echo BigRational::of('2/3')->plus('5/6')->multipliedBy('5/4'); // 15/8
183+
```
184+
185+
### Division
155186

156-
##### BigInteger
187+
Division needs a specific API for each number class:
188+
189+
#### BigInteger
157190

158191
By default, dividing a `BigInteger` returns the exact result of the division, or throws an exception if the remainder
159192
of the division is not zero:
@@ -163,7 +196,7 @@ echo BigInteger::of(999)->dividedBy(3); // 333
163196
echo BigInteger::of(1000)->dividedBy(3); // RoundingNecessaryException
164197
```
165198

166-
You can pass an optional [rounding mode](https://github.com/brick/math/blob/0.14.7/src/RoundingMode.php) to round the result, if necessary:
199+
You can pass an optional `RoundingMode` to round the result, if necessary:
167200

168201
```php
169202
echo BigInteger::of(1000)->dividedBy(3, RoundingMode::Down); // 333
@@ -183,10 +216,10 @@ You can even get both at the same time:
183216
[$quotient, $remainder] = BigInteger::of(1000)->quotientAndRemainder(3);
184217
```
185218

186-
##### BigDecimal
219+
#### BigDecimal
187220

188221
Dividing a `BigDecimal` always requires a scale to be specified. If the exact result of the division does not fit in
189-
the given scale, a [rounding mode](https://github.com/brick/math/blob/0.14.7/src/RoundingMode.php) must be provided.
222+
the given scale, a `RoundingMode` must be provided.
190223

191224
```php
192225
echo BigDecimal::of(1)->dividedBy('8', 3); // 0.125
@@ -204,7 +237,7 @@ echo BigDecimal::of(1)->dividedByExact(256); // 0.00390625
204237
echo BigDecimal::of(1)->dividedByExact(11); // RoundingNecessaryException
205238
```
206239

207-
##### BigRational
240+
#### BigRational
208241

209242
The result of the division of a `BigRational` can always be represented exactly:
210243

@@ -213,21 +246,104 @@ echo BigRational::of('13/99')->dividedBy('7'); // 13/693
213246
echo BigRational::of('13/99')->dividedBy('9/8'); // 104/891
214247
```
215248

216-
#### Bitwise operations
217249

218-
`BigInteger` supports bitwise operations:
250+
## String conversion
219251

220-
- `and()`
221-
- `or()`
222-
- `xor()`
223-
- `not()`
252+
All number classes can be converted to string using either the `toString()` method, or the `(string)` cast. For example, the following lines are equivalent:
224253

225-
and bit shifting:
254+
```php
255+
echo BigInteger::of(123)->toString();
256+
echo (string) BigInteger::of(123);
257+
```
226258

227-
- `shiftedLeft()`
228-
- `shiftedRight()`
259+
Different number classes produce different outputs, but will all fold to plain digit strings if they represent a whole number:
260+
261+
```php
262+
echo BigInteger::of(-123)->toString(); // -123
263+
264+
echo BigDecimal::of('1.0')->toString(); // 1.0
265+
echo BigDecimal::of('1')->toString(); // 1
266+
267+
echo BigRational::of('2/3')->toString(); // 2/3
268+
echo BigRational::of('1/1')->toString(); // 1
269+
```
270+
271+
All string outputs are parseable by the `of()` factory method. The following is guaranteed to work:
272+
273+
```php
274+
BigNumber::of($bigNumber->toString());
275+
```
276+
277+
> [!IMPORTANT]
278+
> Because `BigDecimal::toString()` and `BigRational::toString()` can return whole numbers, some numbers can be returned
279+
> as `BigInteger` when parsed using `BigNumber::of()`. If you want to retain the original type when reparsing numbers,
280+
> be sure to use `BigDecimal::of()` or `BigRational::of()`.
281+
282+
### BigRational to decimal string
283+
284+
In addition to the standard rational representation such as `2/3`, rational numbers can be represented as decimal numbers
285+
with a potentially repeating sequence of digits. You can use `toRepeatingDecimalString()` to get this representation:
286+
287+
```php
288+
BigRational::of('1/2')->toRepeatingDecimalString(); // 0.5
289+
BigRational::of('2/3')->toRepeatingDecimalString(); // 0.(6)
290+
BigRational::of('171/70')->toRepeatingDecimalString(); // 2.4(428571)
291+
```
292+
293+
The part in parentheses is the repeating period, if any.
294+
295+
> [!WARNING]
296+
> `BigRational::toRepeatingDecimalString()` is unbounded.
297+
> The repeating period can be as large as `denominator - 1`, so large denominators can require a lot of memory and CPU time.
298+
> Example: `BigRational::of('1/100019')->toRepeatingDecimalString()` has a repeating period of 100,018 digits.
299+
300+
## Sign and comparison
301+
302+
All number classes share the same sign and comparison methods through `BigNumber`.
303+
304+
### Sign methods
305+
306+
Use these methods to inspect the sign of a number:
307+
308+
- `getSign()` returns `-1`, `0`, or `1` for values `< 0`, `= 0`, and `> 0`, respectively.
309+
- `isNegative()`
310+
- `isNegativeOrZero()`
311+
- `isZero()`
312+
- `isPositiveOrZero()`
313+
- `isPositive()`
314+
315+
```php
316+
$n = BigDecimal::of('-12.5');
317+
318+
$n->getSign(); // -1
319+
$n->isNegative(); // true
320+
$n->isZero(); // false
321+
```
322+
323+
### Comparison methods
324+
325+
Comparison works across all number classes (`BigInteger`, `BigDecimal`, `BigRational`):
229326

230-
#### Exceptions
327+
- `compareTo()` returns `-1`, `0`, or `1` if this number is `<`, `=`, or `>` than the given number.
328+
- `isEqualTo()`
329+
- `isLessThan()`
330+
- `isLessThanOrEqualTo()`
331+
- `isGreaterThan()`
332+
- `isGreaterThanOrEqualTo()`
333+
334+
```php
335+
$a = BigInteger::of('10');
336+
$b = BigDecimal::of('10.0');
337+
$c = BigRational::of('21/2');
338+
339+
$a->compareTo('11'); // -1
340+
$a->isEqualTo($b); // true
341+
$c->isGreaterThan($a); // true
342+
```
343+
344+
You can also use `min()`, `max()`, and `clamp()` to compare and bound values.
345+
346+
## Exceptions
231347

232348
All exceptions thrown by this library implement the `MathException` interface.
233349
This means that you can safely catch all exceptions thrown by this library using a single catch clause:
@@ -237,26 +353,45 @@ use Brick\Math\BigDecimal;
237353
use Brick\Math\Exception\MathException;
238354

239355
try {
240-
$number = BigDecimal::of('1.234')->dividedBy(3);
356+
$number = BigInteger::of(1)->dividedBy(3);
241357
} catch (MathException $e) {
242358
// ...
243359
}
244360
```
245361

246-
If you need more granular control over the exceptions thrown, you can catch the specific exception classes:
362+
If you need more granular control over the exceptions thrown, you can catch the specific exception classes documented in each method:
247363

248364
- `DivisionByZeroException`
249365
- `IntegerOverflowException`
250366
- `InvalidArgumentException`
251367
- `NegativeNumberException`
252368
- `NoInverseException`
253369
- `NumberFormatException`
370+
- `RandomSourceException`
254371
- `RoundingNecessaryException`
255372

256-
#### Serialization
373+
## Bitwise operations
374+
375+
`BigInteger` supports bitwise operations:
376+
377+
- `and()`
378+
- `or()`
379+
- `xor()`
380+
- `not()`
381+
382+
and bit shifting:
383+
384+
- `shiftedLeft()`
385+
- `shiftedRight()`
386+
387+
## Serialization
257388

258389
`BigInteger`, `BigDecimal` and `BigRational` can be safely serialized on a machine and unserialized on another,
259390
even if these machines do not share the same set of PHP extensions.
260391

261392
For example, serializing on a machine with GMP support and unserializing on a machine that does not have this extension
262393
installed will still work as expected.
394+
395+
## Release process
396+
397+
This library follows [semantic versioning](https://semver.org/).

0 commit comments

Comments
 (0)