You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tired of inprecise numbers represented by doubles, which have to store rational and irrational numbers like PI or sqrt(2) the same way? Obviously the following problem is preventable:
7
+
Are you frustrated by the imprecision of floating-point numbers like doubles, which store both rational and irrational numbers such as π or √2 in the same limited way? This often leads to preventable issues like:
8
8
9
9
```javascript
10
10
1/98*98// = 0.9999999999999999
11
11
```
12
12
13
-
If you need more precision or just want a fraction as a result, just include *Fraction.js*:
13
+
If you require greater precision or prefer to work with fractions instead of decimals, you can easily integrate *Fraction.js* into your project:
14
14
15
15
```javascript
16
-
var Fraction =require('fraction.js');
17
-
// or
18
16
importFractionfrom'fraction.js';
17
+
// or
18
+
var Fraction =require('fraction.js');
19
19
```
20
20
21
-
and give it a trial:
21
+
Here’s an example of how it resolves the issue:
22
22
23
23
```javascript
24
24
Fraction(1).div(98).mul(98) // = 1
25
25
```
26
26
27
-
Internally, numbers are represented as *numerator / denominator*, which adds just a little overhead. However, the library is written with performance and accuracy in mind, which makes it the perfect basis for [Polynomial.js](https://github.com/infusion/Polynomial.js) and [Math.js](https://github.com/josdejong/mathjs).
27
+
Internally, *Fraction.js* represents numbers as *numerator/denominator*, adding only minimal overhead. The library is optimized for both performance and precision, making it an excellent foundation for other libs like [Polynomial.js](https://github.com/infusion/Polynomial.js) and [Math.js](https://github.com/josdejong/mathjs).
28
+
29
+
## Convert Decimal to Fraction
30
+
31
+
One of the core functionalities of *Fraction.js* is its ability to convert decimals into fractions with ease:
28
32
29
-
Convert decimal to fraction
30
-
===
31
-
The simplest job for fraction.js is to get a fraction out of a decimal:
32
33
```javascript
33
-
var x =newFraction(1.88);
34
-
var res =x.toFraction(true); //String "1 22/25"
34
+
let x =newFraction(1.88);
35
+
let res =x.toFraction(true); //Returns "1 22/25" as a string
35
36
```
36
37
37
-
Examples / Motivation
38
-
===
39
-
A simple example might be
38
+
This is particularly useful when you need precise fraction representations instead of dealing with the limitations of floating-point arithmetic. What if you allow some error tolerance?
39
+
40
+
```javascript
41
+
let x =newFraction(0.33333);
42
+
let res =x.simplify(0.001) // Error < 0.001
43
+
.toFraction(); // Returns "1/3" as a string
44
+
```
45
+
46
+
## Precision
47
+
48
+
With the growing adoption of native `BigInt` support in JavaScript, libraries like *Fraction.js* have embraced it for handling arbitrary precision. This enables enhanced performance and accuracy in mathematical operations involving large integers, offering a more reliable solution for applications requiring precision beyond the typical constraints of floating-point `Number` types.
49
+
50
+
## Examples / Motivation
51
+
52
+
A simple example of using *Fraction.js* might look like this:
40
53
41
54
```javascript
42
55
var f =newFraction("9.4'31'"); // 9.4313131313131...
You could of course also access the sign (s), numerator (n) and denominator (d) on your own:
64
+
65
+
Additionally, you can access the internal components of the fraction, such as the sign (s), numerator (n), and denominator (d). Keep in mind that these values are stored as `BigInt`:
If you would try to calculate it yourself, you would come up with something like:
71
+
If you attempted to calculate this manually using floating-point arithmetic, you'd get something like:
56
72
57
73
```javascript
58
74
(9.4313131* (-4/3)) %4.888888=-2.797308133...
59
75
```
60
76
61
-
Quite okay, but yea - not as accurate as it could be.
77
+
While the result is reasonably close, it’s not as accurate as the fraction-based approach that *Fraction.js* provides, especially when dealing with repeating decimals or complex operations. This highlights the value of precision that the library brings.
78
+
79
+
### Laplace Probability
80
+
81
+
A simple example of using *Fraction.js* to calculate probabilities. Let’s find the probability of throwing specific outcomes with a fair die:
62
82
83
+
-**P({3})**: The probability of rolling a 3.
84
+
-**P({1, 4})**: The probability of rolling either 1 or 4.
85
+
-**P({2, 4, 6})**: The probability of rolling 2, 4, or 6.
63
86
64
-
Laplace Probability
65
-
===
66
-
Simple example. What's the probability of throwing a 3, and 1 or 4, and 2 or 4 or 6 with a fair dice?
87
+
#### P({3}):
67
88
68
-
P({3}):
69
89
```javascript
70
-
var p =newFraction([3].length, 6).toString(); // 0.1(6)
90
+
var p =newFraction([3].length, 6).toString(); //"0.1(6)"
71
91
```
72
92
73
-
P({1, 4}):
93
+
#### P({1, 4}):
94
+
74
95
```javascript
75
-
var p =newFraction([1, 4].length, 6).toString(); // 0.(3)
96
+
var p =newFraction([1, 4].length, 6).toString(); //"0.(3)"
76
97
```
77
98
78
-
P({2, 4, 6}):
99
+
#### P({2, 4, 6}):
100
+
79
101
```javascript
80
-
var p =newFraction([2, 4, 6].length, 6).toString(); // 0.5
102
+
var p =newFraction([2, 4, 6].length, 6).toString(); //"0.5"
81
103
```
82
104
83
-
Convert degrees/minutes/seconds to precise rational representation:
84
-
===
105
+
###Convert degrees/minutes/seconds to precise rational representation:
Now it's getting messy ;d To approximate a number like *sqrt(5) - 2* with a numerator and denominator, you can reformat the equation as follows: *pow(n / d + 2, 2) = 5*.
100
122
@@ -111,7 +133,7 @@ for (var n = 0; n <= 10; n++) {
111
133
112
134
console.log(n +"\t"+ a +"\t"+ b +"\t"+ c +"\t"+ x);
113
135
114
-
if (c.add(2).pow(2) <5) {
136
+
if (c.add(2).pow(2).valueOf()<5) {
115
137
a = c;
116
138
x ="1";
117
139
} else {
@@ -139,21 +161,21 @@ n a[n] b[n] c[n] x[n]
139
161
9 15/64 121/512 241/1024 0
140
162
10 241/1024 121/512 483/2048 1
141
163
```
164
+
142
165
Thus the approximation after 11 iterations of the bisection method is *483 / 2048* and the binary representation is 0.00111100011 (see [WolframAlpha](http://www.wolframalpha.com/input/?i=sqrt%285%29-2+binary))
143
166
167
+
I published another example on how to approximate PI with fraction.js on my [blog](https://raw.org/article/rational-numbers-in-javascript/) (Still not the best idea to approximate irrational numbers, but it illustrates the capabilities of Fraction.js perfectly).
144
168
145
-
I published another example on how to approximate PI with fraction.js on my [blog](http://www.xarg.org/2014/03/precise-calculations-in-javascript/) (Still not the best idea to approximate irrational numbers, but it illustrates the capabilities of Fraction.js perfectly).
The behaviour on negative congruences is different to most modulo implementations in computer science. Even the *mod()* function of Fraction.js behaves in the typical way. To solve the problem of having the mathematical correct modulo with Fraction.js you could come up with this:
158
180
159
181
```javascript
@@ -174,29 +196,29 @@ It turns out that Fraction.js outperforms almost any fmod() implementation, incl
174
196
The equation *fmod(4.55, 0.05)* gives *0.04999999999999957*, wolframalpha says *1/20*. The correct answer should be **zero**, as 0.05 divides 4.55 without any remainder.
175
197
176
198
177
-
Parser
178
-
===
199
+
##Parser
200
+
179
201
180
202
Any function (see below) as well as the constructor of the *Fraction* class parses its input and reduce it to the smallest term.
181
203
182
204
You can pass either Arrays, Objects, Integers, Doubles or Strings.
183
205
184
-
Arrays / Objects
185
-
---
206
+
###Arrays / Objects
207
+
186
208
```javascript
187
209
newFraction(numerator, denominator);
188
210
newFraction([numerator, denominator]);
189
211
newFraction({n: numerator, d: denominator});
190
212
```
191
213
192
-
Integers
193
-
---
214
+
###Integers
215
+
194
216
```javascript
195
217
newFraction(123);
196
218
```
197
219
198
-
Doubles
199
-
---
220
+
###Doubles
221
+
200
222
```javascript
201
223
newFraction(55.4);
202
224
```
@@ -206,8 +228,8 @@ new Fraction(55.4);
206
228
The method is really precise, but too large exact numbers, like 1234567.9991829 will result in a wrong approximation. If you want to keep the number as it is, convert it to a string, as the string parser will not perform any further observations. If you have problems with the approximation, in the file `examples/approx.js` is a different approximation algorithm, which might work better in some more specific use-cases.
207
229
208
230
209
-
Strings
210
-
---
231
+
###Strings
232
+
211
233
```javascript
212
234
newFraction("123.45");
213
235
newFraction("123/45"); // A rational number represented as two decimals, separated by a slash
@@ -219,14 +241,14 @@ new Fraction("123.45'6'"); // Note the quotes, see below!
219
241
newFraction("123.45(6)"); // Note the brackets, see below!
220
242
```
221
243
222
-
Two arguments
223
-
---
244
+
###Two arguments
245
+
224
246
```javascript
225
247
newFraction(3, 2); // 3/2 = 1.5
226
248
```
227
249
228
-
Repeating decimal places
229
-
---
250
+
### Repeating decimal places
251
+
230
252
*Fraction.js* can easily handle repeating decimal places. For example *1/3* is *0.3333...*. There is only one repeating digit. As you can see in the examples above, you can pass a number like *1/3* as "0.'3'" or "0.(3)", which are synonym. There are no tests to parse something like 0.166666666 to 1/6! If you really want to handle this number, wrap around brackets on your own with the function below for example: 0.1(66666666)
231
253
232
254
Assume you want to divide 123.32 / 33.6(567). [WolframAlpha](http://www.wolframalpha.com/input/?i=123.32+%2F+%2812453%2F370%29) states that you'll get a period of 1776 digits. *Fraction.js* comes to the same result. Give it a try:
@@ -275,8 +297,8 @@ if (x !== null) {
275
297
}
276
298
```
277
299
278
-
Attributes
279
-
===
300
+
##Attributes
301
+
280
302
281
303
The Fraction object allows direct access to the numerator, denominator and sign attributes. It is ensured that only the sign-attribute holds sign information so that a sign comparison is only necessary against this attribute.
282
304
@@ -288,8 +310,8 @@ console.log(f.s); // Sign: -1
288
310
```
289
311
290
312
291
-
Functions
292
-
===
313
+
##Functions
314
+
293
315
294
316
Fraction abs()
295
317
---
@@ -386,17 +408,17 @@ Generates an exact string representation of the actual object. For repeated deci
386
408
387
409
**Note:** As `valueOf()` and `toString()` are provided, `toString()` is only called implicitly in a real string context. Using the plus-operator like `"123" + new Fraction` will call valueOf(), because JavaScript tries to combine two primitives first and concatenates them later, as string will be the more dominant type. `alert(new Fraction)` or `String(new Fraction)` on the other hand will do what you expect. If you really want to have control, you should call `toString()` or `valueOf()` explicitly!
388
410
389
-
String toLatex(excludeWhole=false)
411
+
String toLatex(showMixed=false)
390
412
---
391
-
Generates an exact LaTeX representation of the actual object. You can see a [live demo](http://www.xarg.org/2014/03/precise-calculations-in-javascript/) on my blog.
413
+
Generates an exact LaTeX representation of the actual object. You can see a [live demo](https://raw.org/article/rational-numbers-in-javascript/) on my blog.
392
414
393
-
The optional boolean parameter indicates if you want to exclude the whole part. "1 1/3" instead of "4/3"
415
+
The optional boolean parameter indicates if you want to show the a mixed fraction. "1 1/3" instead of "4/3"
394
416
395
-
String toFraction(excludeWhole=false)
417
+
String toFraction(showMixed=false)
396
418
---
397
419
Gets a string representation of the fraction
398
420
399
-
The optional boolean parameter indicates if you want to exclude the whole part. "1 1/3" instead of "4/3"
421
+
The optional boolean parameter indicates if you want to showa mixed fraction. "1 1/3" instead of "4/3"
400
422
401
423
Array toContinued()
402
424
---
@@ -412,55 +434,58 @@ Fraction clone()
412
434
Creates a copy of the actual Fraction object
413
435
414
436
415
-
Exceptions
416
-
===
417
-
If a really hard error occurs (parsing error, division by zero), *fraction.js* throws exceptions! Please make sure you handle them correctly.
437
+
##Exceptions
438
+
439
+
If a really hard error occurs (parsing error, division by zero), *Fraction.js* throws exceptions! Please make sure you handle them correctly.
418
440
419
441
442
+
##Installation
420
443
421
-
Installation
422
-
===
423
444
Installing fraction.js is as easy as cloning this repo or use the following command:
424
445
425
-
```
446
+
```bash
426
447
npm install fraction.js
427
448
```
428
449
429
-
Using Fraction.js with the browser
430
-
===
450
+
##Using Fraction.js with the browser
451
+
431
452
```html
432
-
<scriptsrc="fraction.js"></script>
453
+
<scriptsrc="fraction.min.js"></script>
433
454
<script>
434
455
console.log(Fraction("123/456"));
435
456
</script>
436
457
```
437
458
438
-
Using Fraction.js with TypeScript
439
-
===
459
+
##Using Fraction.js with TypeScript
460
+
440
461
```js
441
462
importFractionfrom"fraction.js";
442
463
console.log(Fraction("123/456"));
443
464
```
444
465
445
-
Coding Style
446
-
===
447
-
As every library I publish, fraction.js is also built to be as small as possible after compressing it with Google Closure Compiler in advanced mode. Thus the coding style orientates a little on maxing-out the compression rate. Please make sure you keep this style if you plan to extend the library.
448
466
467
+
##Coding Style
468
+
469
+
As every library I publish, Fraction.js is also built to be as small as possible after compressing it with Google Closure Compiler in advanced mode. Thus the coding style orientates a little on maxing-out the compression rate. Please make sure you keep this style if you plan to extend the library.
449
470
450
-
Precision
451
-
===
452
-
Fraction.js tries to circumvent floating point errors, by having an internal representation of numerator and denominator. As it relies on JavaScript, there is also a limit. The biggest number representable is `Number.MAX_SAFE_INTEGER / 1` and the smallest is `-1 / Number.MAX_SAFE_INTEGER`, with `Number.MAX_SAFE_INTEGER=9007199254740991`. If this is not enough, there is `bigfraction.js` shipped experimentally, which relies on `BigInt` and should become the new Fraction.js eventually.
471
+
##Building the library
453
472
454
-
Testing
455
-
===
456
-
If you plan to enhance the library, make sure you add test cases and all the previous tests are passing. You can test the library with
473
+
After cloning the Git repository run:
457
474
475
+
```bash
476
+
npm install
477
+
npm run build
458
478
```
459
-
npm test
479
+
480
+
##Run a test
481
+
482
+
Testing the source against the shipped test suite is as easy as
0 commit comments