|
7 | 7 | - multiplication (`multiply`)
|
8 | 8 | - division (`divide`)
|
9 | 9 | - remainder (`remainder`)
|
10 |
| -- absolute value (`abs`) |
| 10 | +- rounding (`round`) |
11 | 11 | - `toString`
|
12 |
| -- `toExponential` |
13 | 12 |
|
14 | 13 | ## Implementation
|
15 | 14 |
|
16 |
| -This package is written in TypeScript. Unit tests are in (typed) Jest. There are no other external dependencies. |
| 15 | +This package is written in TypeScript. Unit tests are in Jest. There are no other external dependencies. |
17 | 16 |
|
18 | 17 | ## Data model
|
19 | 18 |
|
20 | 19 | This package aims to reproduce the IEEE 754 [Decimal128](https://en.wikipedia.org/wiki/Decimal128_floating-point_format) decimal floating-point numbers in JavaScript. These **decimal** (not binary!) numbers take up 128 bits of information per number. This format allows for an exact representation of decimal numbers with 34 (decimal) significant digits and an exponent between -6143 and 6144. That's a _vast_ amount of range and precision! Decimal128 is a fantastic standard. Let's implement it in JavaScript.
|
21 | 20 |
|
22 |
| -This package also supports minus zero, positive and negative infinity, and NaN. |
23 |
| - |
24 |
| -This package aims to work with only _normalized_ values in the Decimal128 universe. With this package, there is no way to represent, say, `1.2` and `1.20` as distinct values. Digit strings are normalized right away, so `1.20` becomes `1.2`. |
| 21 | +This package also supports minus zero, positive and negative infinity, and NaN. These values are distinct from JS's built-in `-0`, `Infinity`, `-Infinity`, and `NaN`, since those are all JS Numbers. |
25 | 22 |
|
26 | 23 | ### Differences with the official Decimal128
|
27 | 24 |
|
28 |
| -This package is not literally an implementation of Decimal128. In time, it may _become_ one, but initially, this package is working with a subspace of Decimal128 that makes sense for the use cases we have in mind (mainly, finance). |
| 25 | +This package is not literally an implementation of Decimal128. This package is working with a subset of Decimal128 that makes sense for the use cases we have in mind (mainly, though not exclusively, finance). Only a handful of arithmetic operations are implemented. We do not offer, for instance, the various trigonometric functions. |
29 | 26 |
|
30 | 27 | #### Lack of support for specifying context
|
31 | 28 |
|
32 |
| -IEEE 754 Decimal128 allows one to globally specify configuration values (e.g., precision) that control all mathematical operations on Decimal128 values. This JavaScript package does not support that. Calculations are always done using all available digits. |
| 29 | +IEEE 754 Decimal128 allows one to globally specify configuration values (e.g., precision) that control all mathematical operations on Decimal128 values. This JavaScript package does not support that. This package offers a purely functional subset of Decimal128; there's no ambient context to specify and set. If one wishes to control, e.g., rounding, then one needs to specify that when constructing Decimal128 values or doing arithmetic operations. |
| 30 | + |
| 31 | +Think of this package as providing, basically, arbitrary-precision decimal numbers limited to those that fit into 128 bits the way that Decimal128 does it. No need to specify context. Just imagine that you're working in an ideal arbitrary-precision world, do the operation, and enjoy the results. If you need to cut off a calculation after a certain point, just perform the operation (e.g., addition) and use `round`. |
33 | 32 |
|
34 |
| -Think of this package as providing, basically, arbitrary-precision decimal numbers limited to those that fit into 128 bits the way that Decimal128 does it. No need to specify context. Just imagine that you're working in an ideal arbitrary-precision world, do the operation, and enjoy the results. If you need to cut off a calculation after a certain point, just perform the operation (e.g., addition) and then use `toDecimalDigits` on the result. |
| 33 | +#### Serialized values normalized by default |
35 | 34 |
|
36 |
| -#### Values always normalized |
| 35 | +Decimal128 is a universe of **unnormalized** values. In the Decimal128 world, `1.2` and `1.20` are _distinct_ values. There's good reason for adopting such an approach, and has some benefits. But there can be surprises when working with non-normal values. This package supports IEEE 754 Decimal128, but it also aims to minimize surprises. In IEEE 754 Decimal128, if one adds, say, 1.2 and 3.8, the result is 5.0, not 5. (Again, those are *distinct* values in IEEE 754 Decimal128.) Reproducing that example with this package, one has |
37 | 36 |
|
38 |
| -Decimal128 is a universe of **unnormalized** values. In the Decimal128 world, `1.2` and `1.20` are _distinct_ values. There's good reason for adopting such an approach, and some benefits. But this package deliberately works in a world of _normalized_ values. Given the string `1.20`, this package will turn that into `1.2`; that extra trailing zero will be lost. To recover the string `1.20`, additional, out-of-band information needs to be supplied. For instance: if you're working with numbers as financial quantities, you know, out-of-band, how to interpret your numbers. Thus, if I tell you that the cost of something is `1.2` USD, you know that means, and you know that, if you need to present that data to someone, you'd add an extra digit there. This package provides a `toDecimalDigits` method that allows you to generate `1.20` from the underlying `1.2`. |
| 37 | +```javascript |
| 38 | +new Decimal128("1.2").add(new Decimal128("3.8")).toString() // "5" |
| 39 | +``` |
39 | 40 |
|
40 |
| -#### Missing operations |
| 41 | +One can switch off normalization by setting the `normalize` option to `false` in `toString`, like this: |
41 | 42 |
|
42 |
| -This package focuses on the bread and butter of arithmetic: addition, multiplication, subtraction, and division. To round things out from there (ha!), we have the absolute value function, trunction, floor/ceiling. |
| 43 | +```javascript |
| 44 | +new Decimal128("1.2").add(new Decimal128("3.8")).toString({ normalize: false }) // "5.0" |
| 45 | +``` |
0 commit comments