Skip to content

Commit f7ee7a6

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

File tree

1 file changed

+186
-47
lines changed

1 file changed

+186
-47
lines changed

README.md

Lines changed: 186 additions & 47 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,16 @@ 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 numbers of any size:
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`
20+
21+
It works with or without the GMP or BCMath extensions, falling back to a pure-PHP implementation if necessary.
22+
1323
### Installation
1424

1525
This library is installable via [Composer](https://getcomposer.org/):
@@ -22,42 +32,35 @@ composer require brick/math
2232

2333
This library requires PHP 8.2 or later.
2434

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-
2735
Although the library can work seamlessly on any PHP installation, it is highly recommended that you install the
2836
[GMP](http://php.net/manual/en/book.gmp.php) or [BCMath](http://php.net/manual/en/book.bc.php) extension
2937
to speed up calculations. The fastest available calculator implementation will be automatically selected at runtime.
3038

31-
### Project status & release process
39+
## Number classes
3240

33-
While this library is still under development, it is well tested and considered stable enough to use in production
34-
environments.
41+
The three number classes all extend the same `BigNumber` class:
3542

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.
43+
```
44+
Brick\Math\BigNumber
45+
├── Brick\Math\BigInteger
46+
├── Brick\Math\BigDecimal
47+
└── Brick\Math\BigRational
48+
```
4549

46-
### Package contents
50+
`BigNumber` is an abstract class that defines the common behaviour of all number classes:
4751

48-
This library provides the following public classes in the `Brick\Math` namespace:
52+
- `of()` — to obtain an instance
53+
- sign methods: `isZero()`, `isPositive()`, etc.
54+
- comparison methods: `isEqualTo()`, `isGreaterThan()`, etc.
55+
- `min()`, `max()`, `sum()`, `toString()` etc.
4956

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.
57+
Comparison methods work across all number classes, you can for example compare a `BigInteger` to a `BigDecimal`, or a `BigDecimal` to a `BigRational`.
5558

56-
And [exceptions](#exceptions) in the `Brick\Math\Exception` namespace.
59+
All classes work with a virtually unlimited number of digits, and are limited only by available memory and CPU time.
5760

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

60-
#### Instantiation
63+
## Instantiation
6164

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

@@ -89,7 +92,7 @@ BigDecimal::of('1/8'); // 0.125
8992
BigDecimal::of('1/3'); // RoundingNecessaryException
9093

9194
BigRational::of('1.1'); // 11/10
92-
BigRational::of('1.15'); // 23/20 (reduced to lowest terms)
95+
BigRational::of('1.15'); // 23/20
9396
```
9497

9598
> [!NOTE]
@@ -107,7 +110,7 @@ BigRational::of('1.15'); // 23/20 (reduced to lowest terms)
107110
> BigDecimal::of((string) $float);
108111
> ```
109112
110-
#### Immutability & chaining
113+
## Immutability & chaining
111114
112115
The `BigInteger`, `BigDecimal` and `BigRational` classes are immutable: their value never changes,
113116
so that they can be safely passed around. All methods that return a `BigInteger`, `BigDecimal` or `BigRational`
@@ -126,7 +129,7 @@ The methods can be chained for better readability:
126129
echo BigInteger::of(10)->plus(5)->multipliedBy(3); // 45
127130
```
128131

129-
#### Parameter types
132+
## Parameter types
130133

131134
All methods that accept a number: `plus()`, `minus()`, `multipliedBy()`, etc. accept the same types as `of()`.
132135
For example, given the following number:
@@ -151,9 +154,43 @@ echo BigInteger::of(2)->multipliedBy(BigDecimal::of('2.5')); // RoundingNecessar
151154
echo BigDecimal::of(2.5)->multipliedBy(BigInteger::of(2)); // 5.0
152155
```
153156

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

156-
##### BigInteger
191+
Division needs a specific API for each number class:
192+
193+
#### BigInteger
157194

158195
By default, dividing a `BigInteger` returns the exact result of the division, or throws an exception if the remainder
159196
of the division is not zero:
@@ -163,7 +200,7 @@ echo BigInteger::of(999)->dividedBy(3); // 333
163200
echo BigInteger::of(1000)->dividedBy(3); // RoundingNecessaryException
164201
```
165202

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

168205
```php
169206
echo BigInteger::of(1000)->dividedBy(3, RoundingMode::Down); // 333
@@ -183,10 +220,10 @@ You can even get both at the same time:
183220
[$quotient, $remainder] = BigInteger::of(1000)->quotientAndRemainder(3);
184221
```
185222

186-
##### BigDecimal
223+
#### BigDecimal
187224

188225
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.
226+
the given scale, a `RoundingMode` must be provided.
190227

191228
```php
192229
echo BigDecimal::of(1)->dividedBy('8', 3); // 0.125
@@ -204,7 +241,7 @@ echo BigDecimal::of(1)->dividedByExact(256); // 0.00390625
204241
echo BigDecimal::of(1)->dividedByExact(11); // RoundingNecessaryException
205242
```
206243

207-
##### BigRational
244+
#### BigRational
208245

209246
The result of the division of a `BigRational` can always be represented exactly:
210247

@@ -213,21 +250,104 @@ echo BigRational::of('13/99')->dividedBy('7'); // 13/693
213250
echo BigRational::of('13/99')->dividedBy('9/8'); // 104/891
214251
```
215252

216-
#### Bitwise operations
217253

218-
`BigInteger` supports bitwise operations:
254+
## String conversion
219255

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

225-
and bit shifting:
258+
```php
259+
echo BigInteger::of(123)->toString();
260+
echo (string) BigInteger::of(123);
261+
```
226262

227-
- `shiftedLeft()`
228-
- `shiftedRight()`
263+
Different number classes produce different outputs, but will all fold to plain digit strings if they represent a whole number:
264+
265+
```php
266+
echo BigInteger::of(-123)->toString(); // -123
267+
268+
echo BigDecimal::of('1.0')->toString(); // 1.0
269+
echo BigDecimal::of('1')->toString(); // 1
270+
271+
echo BigRational::of('2/3')->toString(); // 2/3
272+
echo BigRational::of('1/1')->toString(); // 1
273+
```
274+
275+
All string outputs are parseable by the `of()` factory method. The following is guaranteed to work:
276+
277+
```php
278+
BigNumber::of($bigNumber->toString());
279+
```
229280

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

232352
All exceptions thrown by this library implement the `MathException` interface.
233353
This means that you can safely catch all exceptions thrown by this library using a single catch clause:
@@ -237,26 +357,45 @@ use Brick\Math\BigDecimal;
237357
use Brick\Math\Exception\MathException;
238358

239359
try {
240-
$number = BigDecimal::of('1.234')->dividedBy(3);
360+
$number = BigInteger::of(1)->dividedBy(3);
241361
} catch (MathException $e) {
242362
// ...
243363
}
244364
```
245365

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

248368
- `DivisionByZeroException`
249369
- `IntegerOverflowException`
250370
- `InvalidArgumentException`
251371
- `NegativeNumberException`
252372
- `NoInverseException`
253373
- `NumberFormatException`
374+
- `RandomSourceException`
254375
- `RoundingNecessaryException`
255376

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

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

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

0 commit comments

Comments
 (0)