Skip to content

Commit 526c03f

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

File tree

1 file changed

+186
-49
lines changed

1 file changed

+186
-49
lines changed

README.md

Lines changed: 186 additions & 49 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,31 @@ 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:
45+
```
46+
Brick\Math\BigNumber
47+
├── Brick\Math\BigInteger
48+
├── Brick\Math\BigDecimal
49+
└── Brick\Math\BigRational
50+
```
4951

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.
52+
`BigNumber` is an abstract class that defines the common behaviour of all number classes:
5553

56-
And [exceptions](#exceptions) in the `Brick\Math\Exception` namespace.
54+
- `of()` — to obtain an instance
55+
- sign methods: `isZero()`, `isPositive()`, etc.
56+
- comparison methods: `isEqualTo()`, `isGreaterThan()`, etc.
57+
- `min()`, `max()`, `sum()`, `toString()`, etc.
5758

58-
### Overview
59+
`BigRational` numbers are always simplified to lowest terms, for example `2/6` is automatically simplified to `1/3`.
5960

60-
#### Instantiation
61+
## Instantiation
6162

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

@@ -89,7 +90,7 @@ BigDecimal::of('1/8'); // 0.125
8990
BigDecimal::of('1/3'); // RoundingNecessaryException
9091

9192
BigRational::of('1.1'); // 11/10
92-
BigRational::of('1.15'); // 23/20 (reduced to lowest terms)
93+
BigRational::of('1.15'); // 23/20
9394
```
9495

9596
> [!NOTE]
@@ -107,7 +108,7 @@ BigRational::of('1.15'); // 23/20 (reduced to lowest terms)
107108
> BigDecimal::of((string) $float);
108109
> ```
109110
110-
#### Immutability & chaining
111+
## Immutability & chaining
111112
112113
The `BigInteger`, `BigDecimal` and `BigRational` classes are immutable: their value never changes,
113114
so that they can be safely passed around. All methods that return a `BigInteger`, `BigDecimal` or `BigRational`
@@ -126,7 +127,7 @@ The methods can be chained for better readability:
126127
echo BigInteger::of(10)->plus(5)->multipliedBy(3); // 45
127128
```
128129

129-
#### Parameter types
130+
## Parameter types
130131

131132
All methods that accept a number: `plus()`, `minus()`, `multipliedBy()`, etc. accept the same types as `of()`.
132133
For example, given the following number:
@@ -151,9 +152,43 @@ echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.5')); // RoundingNecessar
151152
echo BigDecimal::of(2.5)->multipliedBy(BigInteger::of(2)); // 5.0
152153
```
153154

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

156-
##### BigInteger
191+
#### BigInteger
157192

158193
By default, dividing a `BigInteger` returns the exact result of the division, or throws an exception if the remainder
159194
of the division is not zero:
@@ -163,7 +198,7 @@ echo BigInteger::of(999)->dividedBy(3); // 333
163198
echo BigInteger::of(1000)->dividedBy(3); // RoundingNecessaryException
164199
```
165200

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:
201+
You can pass an optional `RoundingMode` to round the result, if necessary:
167202

168203
```php
169204
echo BigInteger::of(1000)->dividedBy(3, RoundingMode::Down); // 333
@@ -183,10 +218,10 @@ You can even get both at the same time:
183218
[$quotient, $remainder] = BigInteger::of(1000)->quotientAndRemainder(3);
184219
```
185220

186-
##### BigDecimal
221+
#### BigDecimal
187222

188223
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.
224+
the given scale, a `RoundingMode` must be provided.
190225

191226
```php
192227
echo BigDecimal::of(1)->dividedBy('8', 3); // 0.125
@@ -204,7 +239,7 @@ echo BigDecimal::of(1)->dividedByExact(256); // 0.00390625
204239
echo BigDecimal::of(1)->dividedByExact(11); // RoundingNecessaryException
205240
```
206241

207-
##### BigRational
242+
#### BigRational
208243

209244
The result of the division of a `BigRational` can always be represented exactly:
210245

@@ -213,21 +248,104 @@ echo BigRational::of('13/99')->dividedBy('7'); // 13/693
213248
echo BigRational::of('13/99')->dividedBy('9/8'); // 104/891
214249
```
215250

216-
#### Bitwise operations
217251

218-
`BigInteger` supports bitwise operations:
252+
## String conversion
219253

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

225-
and bit shifting:
256+
```php
257+
echo BigInteger::of(123)->toString();
258+
echo (string) BigInteger::of(123);
259+
```
226260

227-
- `shiftedLeft()`
228-
- `shiftedRight()`
261+
Different number classes produce different outputs, but will all fold to plain digit strings if they represent a whole number:
262+
263+
```php
264+
echo BigInteger::of(-123)->toString(); // -123
265+
266+
echo BigDecimal::of('1.0')->toString(); // 1.0
267+
echo BigDecimal::of('1')->toString(); // 1
229268

230-
#### Exceptions
269+
echo BigRational::of('2/3')->toString(); // 2/3
270+
echo BigRational::of('1/1')->toString(); // 1
271+
```
272+
273+
All string outputs are parseable by the `of()` factory method. The following is guaranteed to work:
274+
275+
```php
276+
BigNumber::of($bigNumber->toString());
277+
```
278+
279+
> [!IMPORTANT]
280+
> Because `BigDecimal::toString()` and `BigRational::toString()` can return whole numbers, some numbers can be returned
281+
> as `BigInteger` when parsed using `BigNumber::of()`. If you want to retain the original type when reparsing numbers,
282+
> be sure to use `BigDecimal::of()` or `BigRational::of()`.
283+
284+
### BigRational to decimal string
285+
286+
In addition to the standard rational representation such as `2/3`, rational numbers can be represented as decimal numbers
287+
with a potentially repeating sequence of digits. You can use `toRepeatingDecimalString()` to get this representation:
288+
289+
```php
290+
BigRational::of('1/2')->toRepeatingDecimalString(); // 0.5
291+
BigRational::of('2/3')->toRepeatingDecimalString(); // 0.(6)
292+
BigRational::of('171/70')->toRepeatingDecimalString(); // 2.4(428571)
293+
```
294+
295+
The part in parentheses is the repeating period, if any.
296+
297+
> [!WARNING]
298+
> `BigRational::toRepeatingDecimalString()` is unbounded.
299+
> The repeating period can be as large as `denominator - 1`, so large denominators can require a lot of memory and CPU time.
300+
> Example: `BigRational::of('1/100019')->toRepeatingDecimalString()` has a repeating period of 100,018 digits.
301+
302+
## Sign and comparison
303+
304+
All number classes share the same sign and comparison methods through `BigNumber`.
305+
306+
### Sign methods
307+
308+
Use these methods to inspect the sign of a number:
309+
310+
- `getSign()` returns `-1`, `0`, or `1` for values `< 0`, `= 0`, and `> 0`, respectively.
311+
- `isNegative()`
312+
- `isNegativeOrZero()`
313+
- `isZero()`
314+
- `isPositiveOrZero()`
315+
- `isPositive()`
316+
317+
```php
318+
$n = BigDecimal::of('-12.5');
319+
320+
$n->getSign(); // -1
321+
$n->isNegative(); // true
322+
$n->isZero(); // false
323+
```
324+
325+
### Comparison methods
326+
327+
Comparison works across all number classes (`BigInteger`, `BigDecimal`, `BigRational`):
328+
329+
- `compareTo()` returns `-1`, `0`, or `1` if this number is `<`, `=`, or `>` than the given number.
330+
- `isEqualTo()`
331+
- `isLessThan()`
332+
- `isLessThanOrEqualTo()`
333+
- `isGreaterThan()`
334+
- `isGreaterThanOrEqualTo()`
335+
336+
```php
337+
$a = BigInteger::of('10');
338+
$b = BigDecimal::of('10.0');
339+
$c = BigRational::of('21/2');
340+
341+
$a->compareTo('11'); // -1
342+
$a->isEqualTo($b); // true
343+
$c->isGreaterThan($a); // true
344+
```
345+
346+
You can also use `min()`, `max()`, and `clamp()` to compare and bound values.
347+
348+
## Exceptions
231349

232350
All exceptions thrown by this library implement the `MathException` interface.
233351
This means that you can safely catch all exceptions thrown by this library using a single catch clause:
@@ -237,26 +355,45 @@ use Brick\Math\BigDecimal;
237355
use Brick\Math\Exception\MathException;
238356

239357
try {
240-
$number = BigDecimal::of('1.234')->dividedBy(3);
358+
$number = BigInteger::of(1)->dividedBy(3);
241359
} catch (MathException $e) {
242360
// ...
243361
}
244362
```
245363

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

248366
- `DivisionByZeroException`
249367
- `IntegerOverflowException`
250368
- `InvalidArgumentException`
251369
- `NegativeNumberException`
252370
- `NoInverseException`
253371
- `NumberFormatException`
372+
- `RandomSourceException`
254373
- `RoundingNecessaryException`
255374

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

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

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

0 commit comments

Comments
 (0)