fraction.js
Advanced tools
Comparing version 4.3.7 to 5.0.0
declare module 'Fraction'; | ||
/** | ||
* Interface representing a fraction with numerator and denominator. | ||
*/ | ||
export interface NumeratorDenominator { | ||
n: number; | ||
d: number; | ||
n: number | BigInt; | ||
d: number | BigInt; | ||
} | ||
type FractionConstructor = { | ||
/** | ||
* Type for handling multiple types of input for Fraction operations. | ||
* Allows passing fractions, numbers, strings, or objects containing | ||
* a numerator and denominator. | ||
*/ | ||
type FractionInput = Fraction | number | string | [number | string, number | string] | NumeratorDenominator; | ||
/** | ||
* Function signature for Fraction operations like add, sub, mul, etc. | ||
* Accepts various types of inputs and returns a Fraction. | ||
*/ | ||
type FractionParam = { | ||
(fraction: Fraction): Fraction; | ||
(num: number | string): Fraction; | ||
(numerator: number, denominator: number): Fraction; | ||
(numbers: [number | string, number | string]): Fraction; | ||
(num: number | BigInt | string): Fraction; | ||
(numerator: number | BigInt, denominator: number | BigInt): Fraction; | ||
(numbers: [number | BigInt | string, number | BigInt | string]): Fraction; | ||
(fraction: NumeratorDenominator): Fraction; | ||
(firstValue: Fraction | number | string | [number | string, number | string] | NumeratorDenominator, secondValue?: number): Fraction; | ||
(firstValue: FractionInput): Fraction; | ||
}; | ||
/** | ||
* Fraction class representing a rational number with numerator and denominator. | ||
* Supports arithmetic, comparison, and formatting operations. | ||
*/ | ||
export default class Fraction { | ||
constructor (fraction: Fraction); | ||
constructor (num: number | string); | ||
constructor (numerator: number, denominator: number); | ||
constructor (numbers: [number | string, number | string]); | ||
constructor (fraction: NumeratorDenominator); | ||
constructor (firstValue: Fraction | number | string | [number | string, number | string] | NumeratorDenominator, secondValue?: number); | ||
/** | ||
* Constructs a new Fraction instance. | ||
* Can accept another Fraction, a number, a string, a tuple, or an object with numerator and denominator. | ||
*/ | ||
constructor(fraction: Fraction); | ||
constructor(num: number | BigInt | string); | ||
constructor(numerator: number | BigInt, denominator: number | BigInt); | ||
constructor(numbers: [number | BigInt | string, number | BigInt | string]); | ||
constructor(fraction: NumeratorDenominator); | ||
constructor(firstValue: FractionInput, secondValue?: number); | ||
s: number; | ||
n: number; | ||
d: number; | ||
/** The sign of the fraction (-1 or 1) */ | ||
s: BigInt; | ||
/** The numerator of the fraction */ | ||
n: BigInt; | ||
/** The denominator of the fraction */ | ||
d: BigInt; | ||
/** Returns the absolute value of the fraction */ | ||
abs(): Fraction; | ||
/** Negates the fraction */ | ||
neg(): Fraction; | ||
add: FractionConstructor; | ||
sub: FractionConstructor; | ||
mul: FractionConstructor; | ||
div: FractionConstructor; | ||
pow: FractionConstructor; | ||
gcd: FractionConstructor; | ||
lcm: FractionConstructor; | ||
mod(n?: number | string | Fraction): Fraction; | ||
/** Adds a fraction or number */ | ||
add: FractionParam; | ||
/** Subtracts a fraction or number */ | ||
sub: FractionParam; | ||
/** Multiplies by a fraction or number */ | ||
mul: FractionParam; | ||
/** Divides by a fraction or number */ | ||
div: FractionParam; | ||
/** Raises the fraction to a given power */ | ||
pow: FractionParam; | ||
/** Finds the greatest common divisor (gcd) with another fraction or number */ | ||
gcd: FractionParam; | ||
/** Finds the least common multiple (lcm) with another fraction or number */ | ||
lcm: FractionParam; | ||
/** | ||
* Returns the modulo of the fraction with respect to another fraction or number. | ||
* If no argument is passed, it returns the fraction modulo 1. | ||
*/ | ||
mod(n?: number | BigInt | string | Fraction): Fraction; | ||
/** Rounds the fraction up to the nearest integer, optionally specifying the number of decimal places */ | ||
ceil(places?: number): Fraction; | ||
/** Rounds the fraction down to the nearest integer, optionally specifying the number of decimal places */ | ||
floor(places?: number): Fraction; | ||
/** Rounds the fraction to the nearest integer, optionally specifying the number of decimal places */ | ||
round(places?: number): Fraction; | ||
/** Rounds the fraction to the nearest multiple of another fraction or number */ | ||
roundTo: FractionParam; | ||
/** Returns the inverse of the fraction (numerator and denominator swapped) */ | ||
inverse(): Fraction; | ||
/** | ||
* Simplifies the fraction to its simplest form. | ||
* Optionally accepts an epsilon value for controlling precision in approximation. | ||
*/ | ||
simplify(eps?: number): Fraction; | ||
equals(n: number | string | Fraction): boolean; | ||
compare(n: number | string | Fraction): number; | ||
divisible(n: number | string | Fraction): boolean; | ||
/** Checks if two fractions or numbers are equal */ | ||
equals(n: number | BigInt | string | Fraction): boolean; | ||
/** Compares two fractions or numbers. Returns -1, 0, or 1 based on the comparison. */ | ||
compare(n: number | BigInt | string | Fraction): number; | ||
/** Checks if the fraction is divisible by another fraction or number */ | ||
divisible(n: number | BigInt | string | Fraction): boolean; | ||
/** Returns the decimal representation of the fraction */ | ||
valueOf(): number; | ||
/** | ||
* Returns a string representation of the fraction. | ||
* Optionally specifies the number of decimal places. | ||
*/ | ||
toString(decimalPlaces?: number): string; | ||
toLatex(excludeWhole?: boolean): string; | ||
toFraction(excludeWhole?: boolean): string; | ||
toContinued(): number[]; | ||
/** | ||
* Returns a LaTeX string representing the fraction. | ||
* Optionally excludes the whole part in the LaTeX string. | ||
*/ | ||
toLatex(showMixed?: boolean): string; | ||
/** | ||
* Returns a string representing the fraction in fraction format. | ||
* Optionally excludes the whole part of the fraction. | ||
*/ | ||
toFraction(showMixed?: boolean): string; | ||
/** Returns an array representing the continued fraction form of the fraction */ | ||
toContinued(): BigInt[]; | ||
/** Returns a clone of the current fraction */ | ||
clone(): Fraction; | ||
} | ||
} |
{ | ||
"name": "fraction.js", | ||
"title": "fraction.js", | ||
"version": "4.3.7", | ||
"homepage": "https://www.xarg.org/2014/03/rational-numbers-in-javascript/", | ||
"title": "Fraction.js", | ||
"version": "5.0.0", | ||
"homepage": "https://raw.org/article/rational-numbers-in-javascript/", | ||
"bugs": "https://github.com/rawify/Fraction.js/issues", | ||
"description": "A rational number library", | ||
"description": "A rational numbers library", | ||
"keywords": [ | ||
@@ -15,42 +15,49 @@ "math", | ||
"parser", | ||
"bigint", | ||
"arbitrary precision", | ||
"rational numbers" | ||
], | ||
"author": { | ||
"name": "Robert Eisele", | ||
"email": "robert@raw.org", | ||
"url": "https://raw.org/" | ||
}, | ||
"type": "module", | ||
"main": "fraction.cjs", | ||
"private": false, | ||
"main": "./dist/fraction.js", | ||
"module": "./dist/fraction.mjs", | ||
"types": "./fraction.d.ts", | ||
"browser": "./dist/fraction.min.js", | ||
"unpkg": "./dist/fraction.min.js", | ||
"readmeFilename": "README.md", | ||
"exports": { | ||
".": { | ||
"import": "./fraction.js", | ||
"require": "./fraction.cjs", | ||
"types": "./fraction.d.ts" | ||
"types": "./fraction.d.ts", | ||
"require": "./dist/fraction.js", | ||
"import": "./dist/fraction.mjs" | ||
} | ||
}, | ||
"types": "./fraction.d.ts", | ||
"private": false, | ||
"readmeFilename": "README.md", | ||
"directories": { | ||
"example": "examples" | ||
}, | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "git://github.com/rawify/Fraction.js.git" | ||
"url": "git@github.com:rawify/Fraction.js.git" | ||
}, | ||
"funding": { | ||
"type": "patreon", | ||
"type": "github", | ||
"url": "https://github.com/sponsors/rawify" | ||
}, | ||
"author": { | ||
"name": "Robert Eisele", | ||
"email": "robert@raw.org", | ||
"url": "https://raw.org/" | ||
}, | ||
"license": "MIT", | ||
"engines": { | ||
"node": "*" | ||
"node": ">= 12" | ||
}, | ||
"directories": { | ||
"example": "examples", | ||
"test": "tests" | ||
}, | ||
"scripts": { | ||
"build": "crude-build Fraction", | ||
"test": "mocha tests/*.js" | ||
}, | ||
"devDependencies": { | ||
"crude-build": "^0.0.1", | ||
"mocha": "*" | ||
} | ||
} |
197
README.md
@@ -7,3 +7,3 @@ # Fraction.js - ℚ in JavaScript | ||
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: | ||
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: | ||
@@ -14,11 +14,11 @@ ```javascript | ||
If you need more precision or just want a fraction as a result, just include *Fraction.js*: | ||
If you require greater precision or prefer to work with fractions instead of decimals, you can easily integrate *Fraction.js* into your project: | ||
```javascript | ||
import Fraction from 'fraction.js'; | ||
// or | ||
var Fraction = require('fraction.js'); | ||
// or | ||
import Fraction from 'fraction.js'; | ||
``` | ||
and give it a trial: | ||
Here’s an example of how it resolves the issue: | ||
@@ -29,31 +29,47 @@ ```javascript | ||
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). | ||
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). | ||
Convert decimal to fraction | ||
=== | ||
The simplest job for fraction.js is to get a fraction out of a decimal: | ||
## Convert Decimal to Fraction | ||
One of the core functionalities of *Fraction.js* is its ability to convert decimals into fractions with ease: | ||
```javascript | ||
var x = new Fraction(1.88); | ||
var res = x.toFraction(true); // String "1 22/25" | ||
let x = new Fraction(1.88); | ||
let res = x.toFraction(true); // Returns "1 22/25" as a string | ||
``` | ||
Examples / Motivation | ||
=== | ||
A simple example might be | ||
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? | ||
```javascript | ||
let x = new Fraction(0.33333); | ||
let res = x.simplify(0.001) // Error < 0.001 | ||
.toFraction(); // Returns "1/3" as a string | ||
``` | ||
## Precision | ||
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. | ||
## Examples / Motivation | ||
A simple example of using *Fraction.js* might look like this: | ||
```javascript | ||
var f = new Fraction("9.4'31'"); // 9.4313131313131... | ||
f.mul([-4, 3]).mod("4.'8'"); // 4.88888888888888... | ||
``` | ||
The result is | ||
The result can then be displayed as: | ||
```javascript | ||
console.log(f.toFraction()); // -4154 / 1485 | ||
``` | ||
You could of course also access the sign (s), numerator (n) and denominator (d) on your own: | ||
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`: | ||
```javascript | ||
f.s * f.n / f.d = -1 * 4154 / 1485 = -2.797306... | ||
Number(f.s) * Number(f.n) / Number(f.d) = -1 * 4154 / 1485 = -2.797306... | ||
``` | ||
If you would try to calculate it yourself, you would come up with something like: | ||
If you attempted to calculate this manually using floating-point arithmetic, you'd get something like: | ||
@@ -64,28 +80,34 @@ ```javascript | ||
Quite okay, but yea - not as accurate as it could be. | ||
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. | ||
### Laplace Probability | ||
Laplace Probability | ||
=== | ||
Simple example. What's the probability of throwing a 3, and 1 or 4, and 2 or 4 or 6 with a fair dice? | ||
A simple example of using *Fraction.js* to calculate probabilities. Let’s find the probability of throwing specific outcomes with a fair die: | ||
P({3}): | ||
- **P({3})**: The probability of rolling a 3. | ||
- **P({1, 4})**: The probability of rolling either 1 or 4. | ||
- **P({2, 4, 6})**: The probability of rolling 2, 4, or 6. | ||
#### P({3}): | ||
```javascript | ||
var p = new Fraction([3].length, 6).toString(); // 0.1(6) | ||
var p = new Fraction([3].length, 6).toString(); // "0.1(6)" | ||
``` | ||
P({1, 4}): | ||
#### P({1, 4}): | ||
```javascript | ||
var p = new Fraction([1, 4].length, 6).toString(); // 0.(3) | ||
var p = new Fraction([1, 4].length, 6).toString(); // "0.(3)" | ||
``` | ||
P({2, 4, 6}): | ||
#### P({2, 4, 6}): | ||
```javascript | ||
var p = new Fraction([2, 4, 6].length, 6).toString(); // 0.5 | ||
var p = new Fraction([2, 4, 6].length, 6).toString(); // "0.5" | ||
``` | ||
Convert degrees/minutes/seconds to precise rational representation: | ||
=== | ||
###Convert degrees/minutes/seconds to precise rational representation: | ||
57+45/60+17/3600 | ||
```javascript | ||
@@ -100,5 +122,5 @@ var deg = 57; // 57° | ||
Rational approximation of irrational numbers | ||
=== | ||
###Rational approximation of irrational numbers | ||
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*. | ||
@@ -119,3 +141,3 @@ | ||
if (c.add(2).pow(2) < 5) { | ||
if (c.add(2).pow(2).valueOf() < 5) { | ||
a = c; | ||
@@ -148,17 +170,17 @@ x = "1"; | ||
``` | ||
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)) | ||
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). | ||
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). | ||
###Get the exact fractional part of a number | ||
Get the exact fractional part of a number | ||
--- | ||
```javascript | ||
var f = new Fraction("-6.(3416)"); | ||
console.log("" + f.mod(1).abs()); // 0.(3416) | ||
console.log(f.mod(1).abs().toFraction()); // = 3416/9999 | ||
``` | ||
Mathematical correct modulo | ||
--- | ||
###Mathematical correct modulo | ||
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: | ||
@@ -184,5 +206,5 @@ | ||
Parser | ||
=== | ||
##Parser | ||
Any function (see below) as well as the constructor of the *Fraction* class parses its input and reduce it to the smallest term. | ||
@@ -192,4 +214,4 @@ | ||
Arrays / Objects | ||
--- | ||
###Arrays / Objects | ||
```javascript | ||
@@ -201,4 +223,4 @@ new Fraction(numerator, denominator); | ||
Integers | ||
--- | ||
###Integers | ||
```javascript | ||
@@ -208,4 +230,4 @@ new Fraction(123); | ||
Doubles | ||
--- | ||
###Doubles | ||
```javascript | ||
@@ -220,4 +242,4 @@ new Fraction(55.4); | ||
Strings | ||
--- | ||
###Strings | ||
```javascript | ||
@@ -234,4 +256,4 @@ new Fraction("123.45"); | ||
Two arguments | ||
--- | ||
###Two arguments | ||
```javascript | ||
@@ -241,4 +263,4 @@ new Fraction(3, 2); // 3/2 = 1.5 | ||
Repeating decimal places | ||
--- | ||
### Repeating decimal places | ||
*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) | ||
@@ -292,5 +314,5 @@ | ||
Attributes | ||
=== | ||
##Attributes | ||
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. | ||
@@ -306,5 +328,5 @@ | ||
Functions | ||
=== | ||
##Functions | ||
Fraction abs() | ||
@@ -405,13 +427,13 @@ --- | ||
String toLatex(excludeWhole=false) | ||
String toLatex(showMixed=false) | ||
--- | ||
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. | ||
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. | ||
The optional boolean parameter indicates if you want to exclude the whole part. "1 1/3" instead of "4/3" | ||
The optional boolean parameter indicates if you want to show the a mixed fraction. "1 1/3" instead of "4/3" | ||
String toFraction(excludeWhole=false) | ||
String toFraction(showMixed=false) | ||
--- | ||
Gets a string representation of the fraction | ||
The optional boolean parameter indicates if you want to exclude the whole part. "1 1/3" instead of "4/3" | ||
The optional boolean parameter indicates if you want to showa mixed fraction. "1 1/3" instead of "4/3" | ||
@@ -432,20 +454,19 @@ Array toContinued() | ||
Exceptions | ||
=== | ||
If a really hard error occurs (parsing error, division by zero), *fraction.js* throws exceptions! Please make sure you handle them correctly. | ||
##Exceptions | ||
If a really hard error occurs (parsing error, division by zero), *Fraction.js* throws exceptions! Please make sure you handle them correctly. | ||
Installation | ||
=== | ||
##Installation | ||
Installing fraction.js is as easy as cloning this repo or use the following command: | ||
``` | ||
```bash | ||
npm install fraction.js | ||
``` | ||
Using Fraction.js with the browser | ||
=== | ||
##Using Fraction.js with the browser | ||
```html | ||
<script src="fraction.js"></script> | ||
<script src="fraction.min.js"></script> | ||
<script> | ||
@@ -456,4 +477,4 @@ console.log(Fraction("123/456")); | ||
Using Fraction.js with TypeScript | ||
=== | ||
##Using Fraction.js with TypeScript | ||
```js | ||
@@ -464,23 +485,27 @@ import Fraction from "fraction.js"; | ||
Coding Style | ||
=== | ||
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. | ||
##Coding Style | ||
Precision | ||
=== | ||
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. | ||
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. | ||
Testing | ||
=== | ||
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 | ||
##Building the library | ||
After cloning the Git repository run: | ||
```bash | ||
npm install | ||
npm run build | ||
``` | ||
npm test | ||
##Run a test | ||
Testing the source against the shipped test suite is as easy as | ||
```bash | ||
npm run test | ||
``` | ||
## Copyright and licensing | ||
Copyright and licensing | ||
=== | ||
Copyright (c) 2023, [Robert Eisele](https://raw.org/) | ||
Copyright (c) 2025, [Robert Eisele](https://raw.org/) | ||
Licensed under the MIT license. |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
89492
2354
492
2
1
No