Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

fraction.js

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fraction.js - npm Package Compare versions

Comparing version
5.2.2
to
5.3.0
+84
fraction.d.mts
/**
* Interface representing a fraction with numerator and denominator.
*/
export interface NumeratorDenominator {
n: number | bigint;
d: number | bigint;
}
/**
* Type for handling multiple types of input for Fraction operations.
*/
export type FractionInput =
| Fraction
| number
| string
| [number | string, number | string]
| NumeratorDenominator;
/**
* Function signature for Fraction operations like add, sub, mul, etc.
*/
export type FractionParam = {
(fraction: Fraction): 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: FractionInput): Fraction;
};
/**
* Fraction class representing a rational number with numerator and denominator.
*/
class Fraction {
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: bigint;
n: bigint;
d: bigint;
abs(): Fraction;
neg(): Fraction;
add: FractionParam;
sub: FractionParam;
mul: FractionParam;
div: FractionParam;
pow: FractionParam;
log: FractionParam;
gcd: FractionParam;
lcm: FractionParam;
mod(n?: number | bigint | string | Fraction): Fraction;
ceil(places?: number): Fraction;
floor(places?: number): Fraction;
round(places?: number): Fraction;
roundTo: FractionParam;
inverse(): Fraction;
simplify(eps?: number): Fraction;
equals(n: number | bigint | string | Fraction): boolean;
lt(n: number | bigint | string | Fraction): boolean;
lte(n: number | bigint | string | Fraction): boolean;
gt(n: number | bigint | string | Fraction): boolean;
gte(n: number | bigint | string | Fraction): boolean;
compare(n: number | bigint | string | Fraction): number;
divisible(n: number | bigint | string | Fraction): boolean;
valueOf(): number;
toString(decimalPlaces?: number): string;
toLatex(showMixed?: boolean): string;
toFraction(showMixed?: boolean): string;
toContinued(): bigint[];
clone(): Fraction;
}
export { Fraction as default, Fraction };
+60
-55

@@ -38,4 +38,6 @@ 'use strict';

const C_TWO = BigInt(2);
const C_THREE = BigInt(3);
const C_FIVE = BigInt(5);
const C_TEN = BigInt(10);
const MAX_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);

@@ -64,3 +66,3 @@ // Maximum search depth for cyclic rational numbers. 2000 should be more than enough.

function trunc(x) {
function ifloor(x) {
return typeof x === 'bigint' ? x : Math.floor(x);

@@ -88,25 +90,25 @@ }

function factorize(num) {
const FACTORSTEPS = [C_TWO * C_TWO, C_TWO, C_TWO * C_TWO, C_TWO, C_TWO * C_TWO, C_TWO * C_THREE, C_TWO, C_TWO * C_THREE]; // repeats
function factorize(n) {
const factors = {};
const factors = Object.create(null);
if (n <= C_ONE) {
factors[n] = C_ONE;
return factors;
}
let n = num;
let i = C_TWO;
let s = C_FIVE - C_ONE;
const add = (p) => { factors[p] = (factors[p] || C_ZERO) + C_ONE; };
while (s <= n) {
while (n % C_TWO === C_ZERO) { add(C_TWO); n /= C_TWO; }
while (n % C_THREE === C_ZERO) { add(C_THREE); n /= C_THREE; }
while (n % C_FIVE === C_ZERO) { add(C_FIVE); n /= C_FIVE; }
while (n % i === C_ZERO) {
n /= i;
factors[i] = (factors[i] || C_ZERO) + C_ONE;
}
s += C_ONE + C_TWO * i++;
// 30-wheel trial division: test only residues coprime to 2*3*5
// Residue step pattern after 5: 7,11,13,17,19,23,29,31, ...
for (let si = 0, p = C_TWO + C_FIVE; p * p <= n;) {
while (n % p === C_ZERO) { add(p); n /= p; }
p += FACTORSTEPS[si];
si = (si + 1) & 7; // fast modulo 8
}
if (n !== num) {
if (n > 1)
factors[n] = (factors[n] || C_ZERO) + C_ONE;
} else {
factors[num] = (factors[num] || C_ZERO) + C_ONE;
}
if (n > C_ONE) add(n);
return factors;

@@ -403,5 +405,5 @@ }

var DivisionByZero = function () { return new Error("Division by Zero"); };
var InvalidParameter = function () { return new Error("Invalid argument"); };
var NonIntegerParameter = function () { return new Error("Parameters must be integer"); };
const DivisionByZero = function () { return new Error("Division by Zero"); };
const InvalidParameter = function () { return new Error("Invalid argument"); };
const NonIntegerParameter = function () { return new Error("Parameters must be integer"); };

@@ -650,3 +652,3 @@ Fraction.prototype = {

const allPrimes = {};
const allPrimes = Object.create(null);

@@ -794,3 +796,3 @@ const baseFactors = factorize(P['n']);

return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) +
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) +
(places * this["n"] % this["d"] > C_ZERO && this["s"] >= C_ZERO ? C_ONE : C_ZERO),

@@ -809,3 +811,3 @@ places);

return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) -
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) -
(places * this["n"] % this["d"] > C_ZERO && this["s"] < C_ZERO ? C_ONE : C_ZERO),

@@ -827,15 +829,15 @@ places);

s >= 0:
round(n / d) = trunc(n / d) + (n % d) / d >= 0.5 ? 1 : 0
= trunc(n / d) + 2(n % d) >= d ? 1 : 0
round(n / d) = ifloor(n / d) + (n % d) / d >= 0.5 ? 1 : 0
= ifloor(n / d) + 2(n % d) >= d ? 1 : 0
s < 0:
round(n / d) =-trunc(n / d) - (n % d) / d > 0.5 ? 1 : 0
=-trunc(n / d) - 2(n % d) > d ? 1 : 0
round(n / d) =-ifloor(n / d) - (n % d) / d > 0.5 ? 1 : 0
=-ifloor(n / d) - 2(n % d) > d ? 1 : 0
=>:
round(s * n / d) = s * trunc(n / d) + s * (C + 2(n % d) > d ? 1 : 0)
round(s * n / d) = s * ifloor(n / d) + s * (C + 2(n % d) > d ? 1 : 0)
where C = s >= 0 ? 1 : 0, to fix the >= for the positve case.
*/
return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) +
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) +
this["s"] * ((this["s"] >= C_ZERO ? C_ONE : C_ZERO) + C_TWO * (places * this["n"] % this["d"]) > this["d"] ? C_ONE : C_ZERO),

@@ -865,4 +867,4 @@ places);

// round(n / d) = trunc(n / d) + 2(n % d) >= d ? 1 : 0
let k = trunc(n / d);
// round(n / d) = ifloor(n / d) + 2(n % d) >= d ? 1 : 0
let k = ifloor(n / d);
if (r + r >= d) {

@@ -882,3 +884,4 @@ k++;

parse(a, b);
return !(!(P["n"] * this["d"]) || ((this["n"] * P["d"]) % (P["n"] * this["d"])));
if (P['n'] === C_ZERO) return false;
return (this['n'] * P['d']) % (P['n'] * this['d']) === C_ZERO;
},

@@ -892,4 +895,5 @@

'valueOf': function () {
// Best we can do so far
return Number(this["s"] * this["n"]) / Number(this["d"]);
//if (this['n'] <= MAX_INTEGER && this['d'] <= MAX_INTEGER) {
return Number(this['s'] * this['n']) / Number(this['d']);
//}
},

@@ -902,3 +906,3 @@

**/
'toString': function (dec) {
'toString': function (dec = 15) {

@@ -908,4 +912,2 @@ let N = this["n"];

dec = dec || 15; // 15 = decimal places when no repetition
let cycLen = cycleLen(N, D); // Cycle length

@@ -917,3 +919,3 @@ let cycOff = cycleStart(N, D, cycLen); // Cycle start

// Append integer part
str += trunc(N / D);
str += ifloor(N / D);

@@ -929,3 +931,3 @@ N %= D;

for (let i = cycOff; i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -936,3 +938,3 @@ N *= C_TEN;

for (let i = cycLen; i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -944,3 +946,3 @@ N *= C_TEN;

for (let i = dec; N && i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -958,3 +960,3 @@ N *= C_TEN;

**/
'toFraction': function (showMixed) {
'toFraction': function (showMixed = false) {

@@ -968,3 +970,3 @@ let n = this["n"];

} else {
let whole = trunc(n / d);
const whole = ifloor(n / d);
if (showMixed && whole > C_ZERO) {

@@ -988,3 +990,3 @@ str += whole;

**/
'toLatex': function (showMixed) {
'toLatex': function (showMixed = false) {

@@ -998,3 +1000,3 @@ let n = this["n"];

} else {
let whole = trunc(n / d);
const whole = ifloor(n / d);
if (showMixed && whole > C_ZERO) {

@@ -1023,18 +1025,21 @@ str += whole;

let b = this['d'];
let res = [];
const res = [];
do {
res.push(trunc(a / b));
let t = a % b;
while (b) {
res.push(ifloor(a / b));
const t = a % b;
a = b;
b = t;
} while (a !== C_ONE);
}
return res;
},
"simplify": function (eps) {
"simplify": function (eps = 1e-3) {
const ieps = BigInt(1 / (eps || 0.001) | 0);
// Continued fractions give best approximations for a max denominator,
// generally outperforming mediants in denominator–accuracy trade-offs.
// Semiconvergents can further reduce the denominator within tolerance.
const ieps = BigInt(Math.ceil(1 / eps));
const thisABS = this['abs']();

@@ -1041,0 +1046,0 @@ const cont = thisABS['toContinued']();

/*
Fraction.js v5.2.2 3/30/2025
Fraction.js v5.3.0 8/16/2025
https://raw.org/article/rational-numbers-in-javascript/

@@ -8,15 +8,15 @@

*/
'use strict';(function(E){function C(){return Error("Parameters must be integer")}function w(){return Error("Invalid argument")}function A(){return Error("Division by Zero")}function p(a,b){var d=g,c=h;let f=h;if(void 0!==a&&null!==a)if(void 0!==b){if("bigint"===typeof a)d=a;else{if(isNaN(a))throw w();if(0!==a%1)throw C();d=BigInt(a)}if("bigint"===typeof b)c=b;else{if(isNaN(b))throw w();if(0!==b%1)throw C();c=BigInt(b)}f=d*c}else if("object"===typeof a){if("d"in a&&"n"in a)d=BigInt(a.n),c=BigInt(a.d),
"s"in a&&(d*=BigInt(a.s));else if(0 in a)d=BigInt(a[0]),1 in a&&(c=BigInt(a[1]));else if("bigint"===typeof a)d=a;else throw w();f=d*c}else if("number"===typeof a){if(isNaN(a))throw w();0>a&&(f=-h,a=-a);if(0===a%1)d=BigInt(a);else{b=1;var k=0,l=1,m=1;let q=1;1<=a&&(b=10**Math.floor(1+Math.log10(a)),a/=b);for(;1E7>=l&&1E7>=q;)if(c=(k+m)/(l+q),a===c){1E7>=l+q?(d=k+m,c=l+q):q>l?(d=m,c=q):(d=k,c=l);break}else a>c?(k+=m,l+=q):(m+=k,q+=l),1E7<l?(d=m,c=q):(d=k,c=l);d=BigInt(d)*BigInt(b);c=BigInt(c)}}else if("string"===
typeof a){c=0;k=b=d=g;l=m=h;a=a.replace(/_/g,"").match(/\d+|./g);if(null===a)throw w();"-"===a[c]?(f=-h,c++):"+"===a[c]&&c++;if(a.length===c+1)b=v(a[c++],f);else if("."===a[c+1]||"."===a[c]){"."!==a[c]&&(d=v(a[c++],f));c++;if(c+1===a.length||"("===a[c+1]&&")"===a[c+3]||"'"===a[c+1]&&"'"===a[c+3])b=v(a[c],f),m=r**BigInt(a[c].length),c++;if("("===a[c]&&")"===a[c+2]||"'"===a[c]&&"'"===a[c+2])k=v(a[c+1],f),l=r**BigInt(a[c+1].length)-h,c+=3}else"/"===a[c+1]||":"===a[c+1]?(b=v(a[c],f),m=v(a[c+2],h),c+=
3):"/"===a[c+3]&&" "===a[c+1]&&(d=v(a[c],f),b=v(a[c+2],f),m=v(a[c+4],h),c+=5);if(a.length<=c)c=m*l,f=d=k+c*d+l*b;else throw w();}else if("bigint"===typeof a)f=d=a,c=h;else throw w();if(c===g)throw A();e.s=f<g?-h:h;e.n=d<g?-d:d;e.d=c<g?-c:c}function v(a,b){try{a=BigInt(a)}catch(d){throw w();}return a*b}function t(a){return"bigint"===typeof a?a:Math.floor(a)}function n(a,b){if(b===g)throw A();const d=Object.create(u.prototype);d.s=a<g?-h:h;a=a<g?-a:a;const c=x(a,b);d.n=a/c;d.d=b/c;return d}function y(a){const b=
{};let d=a,c=z,f=B-h;for(;f<=d;){for(;d%c===g;)d/=c,b[c]=(b[c]||g)+h;f+=h+z*c++}d!==a?1<d&&(b[d]=(b[d]||g)+h):b[a]=(b[a]||g)+h;return b}function x(a,b){if(!a)return b;if(!b)return a;for(;;){a%=b;if(!a)return b;b%=a;if(!b)return a}}function u(a,b){p(a,b);if(this instanceof u)a=x(e.d,e.n),this.s=e.s,this.n=e.n/a,this.d=e.d/a;else return n(e.s*e.n,e.d)}"undefined"===typeof BigInt&&(BigInt=function(a){if(isNaN(a))throw Error("");return a});const g=BigInt(0),h=BigInt(1),z=BigInt(2),B=BigInt(5),r=BigInt(10),
e={s:h,n:g,d:h};u.prototype={s:h,n:g,d:h,abs:function(){return n(this.n,this.d)},neg:function(){return n(-this.s*this.n,this.d)},add:function(a,b){p(a,b);return n(this.s*this.n*e.d+e.s*this.d*e.n,this.d*e.d)},sub:function(a,b){p(a,b);return n(this.s*this.n*e.d-e.s*this.d*e.n,this.d*e.d)},mul:function(a,b){p(a,b);return n(this.s*e.s*this.n*e.n,this.d*e.d)},div:function(a,b){p(a,b);return n(this.s*e.s*this.n*e.d,this.d*e.n)},clone:function(){return n(this.s*this.n,this.d)},mod:function(a,b){if(void 0===
a)return n(this.s*this.n%this.d,h);p(a,b);if(g===e.n*this.d)throw A();return n(this.s*e.d*this.n%(e.n*this.d),e.d*this.d)},gcd:function(a,b){p(a,b);return n(x(e.n,this.n)*x(e.d,this.d),e.d*this.d)},lcm:function(a,b){p(a,b);return e.n===g&&this.n===g?n(g,h):n(e.n*this.n,x(e.n,this.n)*x(e.d,this.d))},inverse:function(){return n(this.s*this.d,this.n)},pow:function(a,b){p(a,b);if(e.d===h)return e.s<g?n((this.s*this.d)**e.n,this.n**e.n):n((this.s*this.n)**e.n,this.d**e.n);if(this.s<g)return null;a=y(this.n);
b=y(this.d);let d=h,c=h;for(let f in a)if("1"!==f){if("0"===f){d=g;break}a[f]*=e.n;if(a[f]%e.d===g)a[f]/=e.d;else return null;d*=BigInt(f)**a[f]}for(let f in b)if("1"!==f){b[f]*=e.n;if(b[f]%e.d===g)b[f]/=e.d;else return null;c*=BigInt(f)**b[f]}return e.s<g?n(c,d):n(d,c)},log:function(a,b){p(a,b);if(this.s<=g||e.s<=g)return null;var d={};a=y(e.n);const c=y(e.d);b=y(this.n);const f=y(this.d);for(var k in c)a[k]=(a[k]||g)-c[k];for(var l in f)b[l]=(b[l]||g)-f[l];for(var m in a)"1"!==m&&(d[m]=!0);for(var q in b)"1"!==
q&&(d[q]=!0);l=k=null;for(const D in d)if(m=a[D]||g,d=b[D]||g,m===g){if(d!==g)return null}else if(q=x(d,m),d/=q,m/=q,null===k&&null===l)k=d,l=m;else if(d*l!==k*m)return null;return null!==k&&null!==l?n(k,l):null},equals:function(a,b){p(a,b);return this.s*this.n*e.d===e.s*e.n*this.d},lt:function(a,b){p(a,b);return this.s*this.n*e.d<e.s*e.n*this.d},lte:function(a,b){p(a,b);return this.s*this.n*e.d<=e.s*e.n*this.d},gt:function(a,b){p(a,b);return this.s*this.n*e.d>e.s*e.n*this.d},gte:function(a,b){p(a,
b);return this.s*this.n*e.d>=e.s*e.n*this.d},compare:function(a,b){p(a,b);a=this.s*this.n*e.d-e.s*e.n*this.d;return(g<a)-(a<g)},ceil:function(a){a=r**BigInt(a||0);return n(t(this.s*a*this.n/this.d)+(a*this.n%this.d>g&&this.s>=g?h:g),a)},floor:function(a){a=r**BigInt(a||0);return n(t(this.s*a*this.n/this.d)-(a*this.n%this.d>g&&this.s<g?h:g),a)},round:function(a){a=r**BigInt(a||0);return n(t(this.s*a*this.n/this.d)+this.s*((this.s>=g?h:g)+a*this.n%this.d*z>this.d?h:g),a)},roundTo:function(a,b){p(a,
b);var d=this.n*e.d;a=this.d*e.n;b=d%a;d=t(d/a);b+b>=a&&d++;return n(this.s*d*e.n,e.d)},divisible:function(a,b){p(a,b);return!(!(e.n*this.d)||this.n*e.d%(e.n*this.d))},valueOf:function(){return Number(this.s*this.n)/Number(this.d)},toString:function(a){let b=this.n,d=this.d;a=a||15;var c;a:{for(c=d;c%z===g;c/=z);for(;c%B===g;c/=B);if(c===h)c=g;else{for(var f=r%c,k=1;f!==h;k++)if(f=f*r%c,2E3<k){c=g;break a}c=BigInt(k)}}a:{f=h;k=r;var l=c;let m=h;for(;l>g;k=k*k%d,l>>=h)l&h&&(m=m*k%d);k=m;for(l=0;300>
l;l++){if(f===k){f=BigInt(l);break a}f=f*r%d;k=k*r%d}f=0}k=f;f=this.s<g?"-":"";f+=t(b/d);(b=b%d*r)&&(f+=".");if(c){for(a=k;a--;)f+=t(b/d),b%=d,b*=r;f+="(";for(a=c;a--;)f+=t(b/d),b%=d,b*=r;f+=")"}else for(;b&&a--;)f+=t(b/d),b%=d,b*=r;return f},toFraction:function(a){let b=this.n,d=this.d,c=this.s<g?"-":"";if(d===h)c+=b;else{let f=t(b/d);a&&f>g&&(c+=f,c+=" ",b%=d);c=c+b+"/"+d}return c},toLatex:function(a){let b=this.n,d=this.d,c=this.s<g?"-":"";if(d===h)c+=b;else{let f=t(b/d);a&&f>g&&(c+=f,b%=d);c=
c+"\\frac{"+b+"}{"+d;c+="}"}return c},toContinued:function(){let a=this.n,b=this.d,d=[];do{d.push(t(a/b));let c=a%b;a=b;b=c}while(a!==h);return d},simplify:function(a){a=BigInt(1/(a||.001)|0);const b=this.abs(),d=b.toContinued();for(let f=1;f<d.length;f++){let k=n(d[f-1],h);for(var c=f-2;0<=c;c--)k=k.inverse().add(d[c]);c=k.sub(b);if(c.n*a<c.d)return k.mul(this.s)}return this}};"function"===typeof define&&define.amd?define([],function(){return u}):"object"===typeof exports?(Object.defineProperty(u,
"__esModule",{value:!0}),u["default"]=u,u.Fraction=u,module.exports=u):E.Fraction=u})(this);
'use strict';(function(F){function D(){return Error("Parameters must be integer")}function x(){return Error("Invalid argument")}function C(){return Error("Division by Zero")}function q(a,b){var d=g,c=h;let f=h;if(void 0!==a&&null!==a)if(void 0!==b){if("bigint"===typeof a)d=a;else{if(isNaN(a))throw x();if(0!==a%1)throw D();d=BigInt(a)}if("bigint"===typeof b)c=b;else{if(isNaN(b))throw x();if(0!==b%1)throw D();c=BigInt(b)}f=d*c}else if("object"===typeof a){if("d"in a&&"n"in a)d=BigInt(a.n),c=BigInt(a.d),
"s"in a&&(d*=BigInt(a.s));else if(0 in a)d=BigInt(a[0]),1 in a&&(c=BigInt(a[1]));else if("bigint"===typeof a)d=a;else throw x();f=d*c}else if("number"===typeof a){if(isNaN(a))throw x();0>a&&(f=-h,a=-a);if(0===a%1)d=BigInt(a);else{b=1;var k=0,l=1,m=1;let r=1;1<=a&&(b=10**Math.floor(1+Math.log10(a)),a/=b);for(;1E7>=l&&1E7>=r;)if(c=(k+m)/(l+r),a===c){1E7>=l+r?(d=k+m,c=l+r):r>l?(d=m,c=r):(d=k,c=l);break}else a>c?(k+=m,l+=r):(m+=k,r+=l),1E7<l?(d=m,c=r):(d=k,c=l);d=BigInt(d)*BigInt(b);c=BigInt(c)}}else if("string"===
typeof a){c=0;k=b=d=g;l=m=h;a=a.replace(/_/g,"").match(/\d+|./g);if(null===a)throw x();"-"===a[c]?(f=-h,c++):"+"===a[c]&&c++;if(a.length===c+1)b=w(a[c++],f);else if("."===a[c+1]||"."===a[c]){"."!==a[c]&&(d=w(a[c++],f));c++;if(c+1===a.length||"("===a[c+1]&&")"===a[c+3]||"'"===a[c+1]&&"'"===a[c+3])b=w(a[c],f),m=t**BigInt(a[c].length),c++;if("("===a[c]&&")"===a[c+2]||"'"===a[c]&&"'"===a[c+2])k=w(a[c+1],f),l=t**BigInt(a[c+1].length)-h,c+=3}else"/"===a[c+1]||":"===a[c+1]?(b=w(a[c],f),m=w(a[c+2],h),c+=
3):"/"===a[c+3]&&" "===a[c+1]&&(d=w(a[c],f),b=w(a[c+2],f),m=w(a[c+4],h),c+=5);if(a.length<=c)c=m*l,f=d=k+c*d+l*b;else throw x();}else if("bigint"===typeof a)f=d=a,c=h;else throw x();if(c===g)throw C();e.s=f<g?-h:h;e.n=d<g?-d:d;e.d=c<g?-c:c}function w(a,b){try{a=BigInt(a)}catch(d){throw x();}return a*b}function u(a){return"bigint"===typeof a?a:Math.floor(a)}function n(a,b){if(b===g)throw C();const d=Object.create(v.prototype);d.s=a<g?-h:h;a=a<g?-a:a;const c=y(a,b);d.n=a/c;d.d=b/c;return d}function A(a){const b=
Object.create(null);if(a<=h)return b[a]=h,b;for(;a%p===g;)b[p]=(b[p]||g)+h,a/=p;for(;a%B===g;)b[B]=(b[B]||g)+h,a/=B;for(;a%z===g;)b[z]=(b[z]||g)+h,a/=z;for(let d=0,c=p+z;c*c<=a;){for(;a%c===g;)b[c]=(b[c]||g)+h,a/=c;c+=G[d];d=d+1&7}a>h&&(b[a]=(b[a]||g)+h);return b}function y(a,b){if(!a)return b;if(!b)return a;for(;;){a%=b;if(!a)return b;b%=a;if(!b)return a}}function v(a,b){q(a,b);if(this instanceof v)a=y(e.d,e.n),this.s=e.s,this.n=e.n/a,this.d=e.d/a;else return n(e.s*e.n,e.d)}"undefined"===typeof BigInt&&
(BigInt=function(a){if(isNaN(a))throw Error("");return a});const g=BigInt(0),h=BigInt(1),p=BigInt(2),B=BigInt(3),z=BigInt(5),t=BigInt(10),e={s:h,n:g,d:h},G=[p*p,p,p*p,p,p*p,p*B,p,p*B];v.prototype={s:h,n:g,d:h,abs:function(){return n(this.n,this.d)},neg:function(){return n(-this.s*this.n,this.d)},add:function(a,b){q(a,b);return n(this.s*this.n*e.d+e.s*this.d*e.n,this.d*e.d)},sub:function(a,b){q(a,b);return n(this.s*this.n*e.d-e.s*this.d*e.n,this.d*e.d)},mul:function(a,b){q(a,b);return n(this.s*e.s*
this.n*e.n,this.d*e.d)},div:function(a,b){q(a,b);return n(this.s*e.s*this.n*e.d,this.d*e.n)},clone:function(){return n(this.s*this.n,this.d)},mod:function(a,b){if(void 0===a)return n(this.s*this.n%this.d,h);q(a,b);if(g===e.n*this.d)throw C();return n(this.s*e.d*this.n%(e.n*this.d),e.d*this.d)},gcd:function(a,b){q(a,b);return n(y(e.n,this.n)*y(e.d,this.d),e.d*this.d)},lcm:function(a,b){q(a,b);return e.n===g&&this.n===g?n(g,h):n(e.n*this.n,y(e.n,this.n)*y(e.d,this.d))},inverse:function(){return n(this.s*
this.d,this.n)},pow:function(a,b){q(a,b);if(e.d===h)return e.s<g?n((this.s*this.d)**e.n,this.n**e.n):n((this.s*this.n)**e.n,this.d**e.n);if(this.s<g)return null;a=A(this.n);b=A(this.d);let d=h,c=h;for(let f in a)if("1"!==f){if("0"===f){d=g;break}a[f]*=e.n;if(a[f]%e.d===g)a[f]/=e.d;else return null;d*=BigInt(f)**a[f]}for(let f in b)if("1"!==f){b[f]*=e.n;if(b[f]%e.d===g)b[f]/=e.d;else return null;c*=BigInt(f)**b[f]}return e.s<g?n(c,d):n(d,c)},log:function(a,b){q(a,b);if(this.s<=g||e.s<=g)return null;
var d=Object.create(null);a=A(e.n);const c=A(e.d);b=A(this.n);const f=A(this.d);for(var k in c)a[k]=(a[k]||g)-c[k];for(var l in f)b[l]=(b[l]||g)-f[l];for(var m in a)"1"!==m&&(d[m]=!0);for(var r in b)"1"!==r&&(d[r]=!0);l=k=null;for(const E in d)if(m=a[E]||g,d=b[E]||g,m===g){if(d!==g)return null}else if(r=y(d,m),d/=r,m/=r,null===k&&null===l)k=d,l=m;else if(d*l!==k*m)return null;return null!==k&&null!==l?n(k,l):null},equals:function(a,b){q(a,b);return this.s*this.n*e.d===e.s*e.n*this.d},lt:function(a,
b){q(a,b);return this.s*this.n*e.d<e.s*e.n*this.d},lte:function(a,b){q(a,b);return this.s*this.n*e.d<=e.s*e.n*this.d},gt:function(a,b){q(a,b);return this.s*this.n*e.d>e.s*e.n*this.d},gte:function(a,b){q(a,b);return this.s*this.n*e.d>=e.s*e.n*this.d},compare:function(a,b){q(a,b);a=this.s*this.n*e.d-e.s*e.n*this.d;return(g<a)-(a<g)},ceil:function(a){a=t**BigInt(a||0);return n(u(this.s*a*this.n/this.d)+(a*this.n%this.d>g&&this.s>=g?h:g),a)},floor:function(a){a=t**BigInt(a||0);return n(u(this.s*a*this.n/
this.d)-(a*this.n%this.d>g&&this.s<g?h:g),a)},round:function(a){a=t**BigInt(a||0);return n(u(this.s*a*this.n/this.d)+this.s*((this.s>=g?h:g)+a*this.n%this.d*p>this.d?h:g),a)},roundTo:function(a,b){q(a,b);var d=this.n*e.d;a=this.d*e.n;b=d%a;d=u(d/a);b+b>=a&&d++;return n(this.s*d*e.n,e.d)},divisible:function(a,b){q(a,b);return e.n===g?!1:this.n*e.d%(e.n*this.d)===g},valueOf:function(){return Number(this.s*this.n)/Number(this.d)},toString:function(a=15){let b=this.n,d=this.d;var c;a:{for(c=d;c%p===g;c/=
p);for(;c%z===g;c/=z);if(c===h)c=g;else{for(var f=t%c,k=1;f!==h;k++)if(f=f*t%c,2E3<k){c=g;break a}c=BigInt(k)}}a:{f=h;k=t;var l=c;let m=h;for(;l>g;k=k*k%d,l>>=h)l&h&&(m=m*k%d);k=m;for(l=0;300>l;l++){if(f===k){f=BigInt(l);break a}f=f*t%d;k=k*t%d}f=0}k=f;f=this.s<g?"-":"";f+=u(b/d);(b=b%d*t)&&(f+=".");if(c){for(a=k;a--;)f+=u(b/d),b%=d,b*=t;f+="(";for(a=c;a--;)f+=u(b/d),b%=d,b*=t;f+=")"}else for(;b&&a--;)f+=u(b/d),b%=d,b*=t;return f},toFraction:function(a=!1){let b=this.n,d=this.d,c=this.s<g?"-":"";
if(d===h)c+=b;else{const f=u(b/d);a&&f>g&&(c+=f,c+=" ",b%=d);c=c+b+"/"+d}return c},toLatex:function(a=!1){let b=this.n,d=this.d,c=this.s<g?"-":"";if(d===h)c+=b;else{const f=u(b/d);a&&f>g&&(c+=f,b%=d);c=c+"\\frac{"+b+"}{"+d;c+="}"}return c},toContinued:function(){let a=this.n,b=this.d;const d=[];for(;b;){d.push(u(a/b));const c=a%b;a=b;b=c}return d},simplify:function(a=.001){a=BigInt(Math.ceil(1/a));const b=this.abs(),d=b.toContinued();for(let f=1;f<d.length;f++){let k=n(d[f-1],h);for(var c=f-2;0<=
c;c--)k=k.inverse().add(d[c]);c=k.sub(b);if(c.n*a<c.d)return k.mul(this.s)}return this}};"function"===typeof define&&define.amd?define([],function(){return v}):"object"===typeof exports?(Object.defineProperty(v,"__esModule",{value:!0}),v["default"]=v,v.Fraction=v,module.exports=v):F.Fraction=v})(this);

@@ -38,4 +38,6 @@ 'use strict';

const C_TWO = BigInt(2);
const C_THREE = BigInt(3);
const C_FIVE = BigInt(5);
const C_TEN = BigInt(10);
const MAX_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);

@@ -64,3 +66,3 @@ // Maximum search depth for cyclic rational numbers. 2000 should be more than enough.

function trunc(x) {
function ifloor(x) {
return typeof x === 'bigint' ? x : Math.floor(x);

@@ -88,25 +90,25 @@ }

function factorize(num) {
const FACTORSTEPS = [C_TWO * C_TWO, C_TWO, C_TWO * C_TWO, C_TWO, C_TWO * C_TWO, C_TWO * C_THREE, C_TWO, C_TWO * C_THREE]; // repeats
function factorize(n) {
const factors = {};
const factors = Object.create(null);
if (n <= C_ONE) {
factors[n] = C_ONE;
return factors;
}
let n = num;
let i = C_TWO;
let s = C_FIVE - C_ONE;
const add = (p) => { factors[p] = (factors[p] || C_ZERO) + C_ONE; };
while (s <= n) {
while (n % C_TWO === C_ZERO) { add(C_TWO); n /= C_TWO; }
while (n % C_THREE === C_ZERO) { add(C_THREE); n /= C_THREE; }
while (n % C_FIVE === C_ZERO) { add(C_FIVE); n /= C_FIVE; }
while (n % i === C_ZERO) {
n /= i;
factors[i] = (factors[i] || C_ZERO) + C_ONE;
}
s += C_ONE + C_TWO * i++;
// 30-wheel trial division: test only residues coprime to 2*3*5
// Residue step pattern after 5: 7,11,13,17,19,23,29,31, ...
for (let si = 0, p = C_TWO + C_FIVE; p * p <= n;) {
while (n % p === C_ZERO) { add(p); n /= p; }
p += FACTORSTEPS[si];
si = (si + 1) & 7; // fast modulo 8
}
if (n !== num) {
if (n > 1)
factors[n] = (factors[n] || C_ZERO) + C_ONE;
} else {
factors[num] = (factors[num] || C_ZERO) + C_ONE;
}
if (n > C_ONE) add(n);
return factors;

@@ -403,5 +405,5 @@ }

var DivisionByZero = function () { return new Error("Division by Zero"); };
var InvalidParameter = function () { return new Error("Invalid argument"); };
var NonIntegerParameter = function () { return new Error("Parameters must be integer"); };
const DivisionByZero = function () { return new Error("Division by Zero"); };
const InvalidParameter = function () { return new Error("Invalid argument"); };
const NonIntegerParameter = function () { return new Error("Parameters must be integer"); };

@@ -650,3 +652,3 @@ Fraction.prototype = {

const allPrimes = {};
const allPrimes = Object.create(null);

@@ -794,3 +796,3 @@ const baseFactors = factorize(P['n']);

return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) +
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) +
(places * this["n"] % this["d"] > C_ZERO && this["s"] >= C_ZERO ? C_ONE : C_ZERO),

@@ -809,3 +811,3 @@ places);

return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) -
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) -
(places * this["n"] % this["d"] > C_ZERO && this["s"] < C_ZERO ? C_ONE : C_ZERO),

@@ -827,15 +829,15 @@ places);

s >= 0:
round(n / d) = trunc(n / d) + (n % d) / d >= 0.5 ? 1 : 0
= trunc(n / d) + 2(n % d) >= d ? 1 : 0
round(n / d) = ifloor(n / d) + (n % d) / d >= 0.5 ? 1 : 0
= ifloor(n / d) + 2(n % d) >= d ? 1 : 0
s < 0:
round(n / d) =-trunc(n / d) - (n % d) / d > 0.5 ? 1 : 0
=-trunc(n / d) - 2(n % d) > d ? 1 : 0
round(n / d) =-ifloor(n / d) - (n % d) / d > 0.5 ? 1 : 0
=-ifloor(n / d) - 2(n % d) > d ? 1 : 0
=>:
round(s * n / d) = s * trunc(n / d) + s * (C + 2(n % d) > d ? 1 : 0)
round(s * n / d) = s * ifloor(n / d) + s * (C + 2(n % d) > d ? 1 : 0)
where C = s >= 0 ? 1 : 0, to fix the >= for the positve case.
*/
return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) +
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) +
this["s"] * ((this["s"] >= C_ZERO ? C_ONE : C_ZERO) + C_TWO * (places * this["n"] % this["d"]) > this["d"] ? C_ONE : C_ZERO),

@@ -865,4 +867,4 @@ places);

// round(n / d) = trunc(n / d) + 2(n % d) >= d ? 1 : 0
let k = trunc(n / d);
// round(n / d) = ifloor(n / d) + 2(n % d) >= d ? 1 : 0
let k = ifloor(n / d);
if (r + r >= d) {

@@ -882,3 +884,4 @@ k++;

parse(a, b);
return !(!(P["n"] * this["d"]) || ((this["n"] * P["d"]) % (P["n"] * this["d"])));
if (P['n'] === C_ZERO) return false;
return (this['n'] * P['d']) % (P['n'] * this['d']) === C_ZERO;
},

@@ -892,4 +895,5 @@

'valueOf': function () {
// Best we can do so far
return Number(this["s"] * this["n"]) / Number(this["d"]);
//if (this['n'] <= MAX_INTEGER && this['d'] <= MAX_INTEGER) {
return Number(this['s'] * this['n']) / Number(this['d']);
//}
},

@@ -902,3 +906,3 @@

**/
'toString': function (dec) {
'toString': function (dec = 15) {

@@ -908,4 +912,2 @@ let N = this["n"];

dec = dec || 15; // 15 = decimal places when no repetition
let cycLen = cycleLen(N, D); // Cycle length

@@ -917,3 +919,3 @@ let cycOff = cycleStart(N, D, cycLen); // Cycle start

// Append integer part
str += trunc(N / D);
str += ifloor(N / D);

@@ -929,3 +931,3 @@ N %= D;

for (let i = cycOff; i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -936,3 +938,3 @@ N *= C_TEN;

for (let i = cycLen; i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -944,3 +946,3 @@ N *= C_TEN;

for (let i = dec; N && i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -958,3 +960,3 @@ N *= C_TEN;

**/
'toFraction': function (showMixed) {
'toFraction': function (showMixed = false) {

@@ -968,3 +970,3 @@ let n = this["n"];

} else {
let whole = trunc(n / d);
const whole = ifloor(n / d);
if (showMixed && whole > C_ZERO) {

@@ -988,3 +990,3 @@ str += whole;

**/
'toLatex': function (showMixed) {
'toLatex': function (showMixed = false) {

@@ -998,3 +1000,3 @@ let n = this["n"];

} else {
let whole = trunc(n / d);
const whole = ifloor(n / d);
if (showMixed && whole > C_ZERO) {

@@ -1023,18 +1025,21 @@ str += whole;

let b = this['d'];
let res = [];
const res = [];
do {
res.push(trunc(a / b));
let t = a % b;
while (b) {
res.push(ifloor(a / b));
const t = a % b;
a = b;
b = t;
} while (a !== C_ONE);
}
return res;
},
"simplify": function (eps) {
"simplify": function (eps = 1e-3) {
const ieps = BigInt(1 / (eps || 0.001) | 0);
// Continued fractions give best approximations for a max denominator,
// generally outperforming mediants in denominator–accuracy trade-offs.
// Semiconvergents can further reduce the denominator within tolerance.
const ieps = BigInt(Math.ceil(1 / eps));
const thisABS = this['abs']();

@@ -1041,0 +1046,0 @@ const cont = thisABS['toContinued']();

@@ -11,3 +11,3 @@ /*

// NOTE: This is a nice example, but a stable version of this is served with Polynomial.js:
// https://github.com/infusion/Polynomial.js
// https://github.com/rawify/Polynomial.js

@@ -14,0 +14,0 @@ function integrate(poly) {

@@ -1,40 +0,3 @@

declare module 'Fraction';
/**
* Interface representing a fraction with numerator and denominator.
*/
export interface NumeratorDenominator {
n: number | bigint;
d: number | bigint;
}
/**
* 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 | bigint | string): Fraction;
(numerator: number | bigint, denominator: number | bigint): Fraction;
(numbers: [number | bigint | string, number | bigint | string]): Fraction;
(fraction: NumeratorDenominator): Fraction;
(firstValue: FractionInput): Fraction;
};
/**
* Fraction class representing a rational number with numerator and denominator.
* Supports arithmetic, comparison, and formatting operations.
*/
export class Fraction {
/**
* Constructs a new Fraction instance.
* Can accept another Fraction, a number, a string, a tuple, or an object with numerator and denominator.
*/
declare class Fraction {
constructor(fraction: Fraction);

@@ -44,118 +7,79 @@ constructor(num: number | bigint | string);

constructor(numbers: [number | bigint | string, number | bigint | string]);
constructor(fraction: NumeratorDenominator);
constructor(firstValue: FractionInput, secondValue?: number);
constructor(fraction: Fraction.NumeratorDenominator);
constructor(firstValue: Fraction.FractionInput, secondValue?: 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;
/** Adds a fraction or number */
add: FractionParam;
add: Fraction.FractionParam;
sub: Fraction.FractionParam;
mul: Fraction.FractionParam;
div: Fraction.FractionParam;
pow: Fraction.FractionParam;
log: Fraction.FractionParam;
gcd: Fraction.FractionParam;
lcm: Fraction.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;
/** Calculates the logarithm of a fraction to a given rational base */
log: 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;
roundTo: Fraction.FractionParam;
/** 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;
/** Checks if two fractions or numbers are equal */
equals(n: number | bigint | string | Fraction): boolean;
/** Check if this rational number is less than another */
lt(n: number | bigint | string | Fraction): boolean;
/** Check if this rational number is less than or equal another */
lte(n: number | bigint | string | Fraction): boolean;
/** Check if this rational number is greater than another */
gt(n: number | bigint | string | Fraction): boolean;
/** Check if this rational number is greater than or equal another */
gte(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;
toString(decimalPlaces?: number): string;
toLatex(showMixed?: boolean): string;
toFraction(showMixed?: boolean): string;
toContinued(): bigint[];
clone(): Fraction;
}
declare namespace Fraction {
/**
* Returns a string representation of the fraction.
* Optionally specifies the number of decimal places.
* Interface representing a fraction with numerator and denominator.
*/
toString(decimalPlaces?: number): string;
interface NumeratorDenominator {
n: number | bigint;
d: number | bigint;
}
/**
* Returns a LaTeX string representing the fraction.
* Optionally excludes the whole part in the LaTeX string.
* Type for handling multiple types of input for Fraction operations.
*/
toLatex(showMixed?: boolean): string;
type FractionInput =
| Fraction
| number
| string
| [number | string, number | string]
| NumeratorDenominator;
/**
* Returns a string representing the fraction in fraction format.
* Optionally excludes the whole part of the fraction.
* Function signature for Fraction operations like add, sub, mul, etc.
*/
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;
type FractionParam = {
(fraction: Fraction): 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: FractionInput): Fraction;
};
}
export default Fraction;
export = Fraction;
{
"name": "fraction.js",
"title": "Fraction.js",
"version": "5.2.2",
"version": "5.3.0",
"description": "The RAW rational numbers library",
"homepage": "https://raw.org/article/rational-numbers-in-javascript/",
"bugs": "https://github.com/rawify/Fraction.js/issues",
"description": "A rational numbers library",
"keywords": [

@@ -29,16 +29,37 @@ "math",

"module": "./dist/fraction.mjs",
"types": "./fraction.d.ts",
"browser": "./dist/fraction.min.js",
"unpkg": "./dist/fraction.min.js",
"readmeFilename": "README.md",
"types": "./fraction.d.ts",
"exports": {
".": {
"types": "./fraction.d.ts",
"require": "./dist/fraction.js",
"import": "./dist/fraction.mjs"
"import": {
"types": "./fraction.d.mts",
"default": "./dist/fraction.mjs"
},
"require": {
"types": "./fraction.d.ts",
"default": "./dist/fraction.js"
},
"browser": {
"types": "./fraction.d.ts",
"default": "./dist/fraction.min.js"
},
"default": {
"types": "./fraction.d.ts",
"default": "./dist/fraction.js"
}
},
"./package.json": "./package.json"
},
"typesVersions": {
"<4.7": {
"*": [
"fraction.d.ts"
]
}
},
"sideEffects": false,
"repository": {
"type": "git",
"url": "git@github.com:rawify/Fraction.js.git"
"url": "git+ssh://git@github.com/rawify/Fraction.js.git"
},

@@ -56,3 +77,3 @@ "funding": {

"engines": {
"node": ">= 12"
"node": "*"
},

@@ -59,0 +80,0 @@ "directories": {

+29
-16

@@ -12,10 +12,4 @@ # Fraction.js - ℚ in JavaScript

For applications requiring higher precision or where working with fractions is preferable, consider incorporating *Fraction.js* into your project. Integration is straightforward:
For applications requiring higher precision or where working with fractions is preferable, consider incorporating *Fraction.js* into your project.
```javascript
import Fraction from 'fraction.js';
// Alternatively
var Fraction = require('fraction.js');
```
The library effectively addresses precision issues, as demonstrated below:

@@ -27,3 +21,3 @@

*Fraction.js* uses a `BigInt` representation for both the numerator and denominator, ensuring minimal performance overhead while maximizing accuracy. Its design is optimized for precision, making it an ideal choice as a foundational library for other math tools, such as [Polynomial.js](https://github.com/infusion/Polynomial.js) and [Math.js](https://github.com/josdejong/mathjs).
*Fraction.js* uses a `BigInt` representation for both the numerator and denominator, ensuring minimal performance overhead while maximizing accuracy. Its design is optimized for precision, making it an ideal choice as a foundational library for other math tools, such as [Polynomial.js](https://github.com/rawify/Polynomial.js) and [Math.js](https://github.com/josdejong/mathjs).

@@ -462,3 +456,3 @@ ## Convert Decimal to Fraction

Installing fraction.js is as easy as cloning this repo or use the following command:
You can install `Fraction.js` via npm:

@@ -469,19 +463,38 @@ ```bash

## Using Fraction.js with the browser
Or with yarn:
```bash
yarn add fraction.js
```
Alternatively, download or clone the repository:
```bash
git clone https://github.com/rawify/Fraction.js
```
## Usage
Include the `fraction.min.js` file in your project:
```html
<script src="fraction.min.js"></script>
<script src="path/to/fraction.min.js"></script>
<script>
console.log(Fraction("123/456"));
var x = new Fraction("13/4");
</script>
```
## Using Fraction.js with TypeScript
Or in a Node.js project:
```js
import Fraction from "fraction.js";
console.log(Fraction("123/456"));
```javascript
const Fraction = require('fraction.js');
```
or
```javascript
import Fraction from 'fraction.js';
```
## Coding Style

@@ -488,0 +501,0 @@

/**
* @license Fraction.js v5.2.2 3/30/2025
* @license Fraction.js v5.3.0 8/16/2025
* https://raw.org/article/rational-numbers-in-javascript/

@@ -44,4 +44,6 @@ *

const C_TWO = BigInt(2);
const C_THREE = BigInt(3);
const C_FIVE = BigInt(5);
const C_TEN = BigInt(10);
const MAX_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);

@@ -70,3 +72,3 @@ // Maximum search depth for cyclic rational numbers. 2000 should be more than enough.

function trunc(x) {
function ifloor(x) {
return typeof x === 'bigint' ? x : Math.floor(x);

@@ -94,25 +96,25 @@ }

function factorize(num) {
const FACTORSTEPS = [C_TWO * C_TWO, C_TWO, C_TWO * C_TWO, C_TWO, C_TWO * C_TWO, C_TWO * C_THREE, C_TWO, C_TWO * C_THREE]; // repeats
function factorize(n) {
const factors = {};
const factors = Object.create(null);
if (n <= C_ONE) {
factors[n] = C_ONE;
return factors;
}
let n = num;
let i = C_TWO;
let s = C_FIVE - C_ONE;
const add = (p) => { factors[p] = (factors[p] || C_ZERO) + C_ONE; };
while (s <= n) {
while (n % C_TWO === C_ZERO) { add(C_TWO); n /= C_TWO; }
while (n % C_THREE === C_ZERO) { add(C_THREE); n /= C_THREE; }
while (n % C_FIVE === C_ZERO) { add(C_FIVE); n /= C_FIVE; }
while (n % i === C_ZERO) {
n /= i;
factors[i] = (factors[i] || C_ZERO) + C_ONE;
}
s += C_ONE + C_TWO * i++;
// 30-wheel trial division: test only residues coprime to 2*3*5
// Residue step pattern after 5: 7,11,13,17,19,23,29,31, ...
for (let si = 0, p = C_TWO + C_FIVE; p * p <= n;) {
while (n % p === C_ZERO) { add(p); n /= p; }
p += FACTORSTEPS[si];
si = (si + 1) & 7; // fast modulo 8
}
if (n !== num) {
if (n > 1)
factors[n] = (factors[n] || C_ZERO) + C_ONE;
} else {
factors[num] = (factors[num] || C_ZERO) + C_ONE;
}
if (n > C_ONE) add(n);
return factors;

@@ -409,5 +411,5 @@ }

var DivisionByZero = function () { return new Error("Division by Zero"); };
var InvalidParameter = function () { return new Error("Invalid argument"); };
var NonIntegerParameter = function () { return new Error("Parameters must be integer"); };
const DivisionByZero = function () { return new Error("Division by Zero"); };
const InvalidParameter = function () { return new Error("Invalid argument"); };
const NonIntegerParameter = function () { return new Error("Parameters must be integer"); };

@@ -656,3 +658,3 @@ Fraction.prototype = {

const allPrimes = {};
const allPrimes = Object.create(null);

@@ -800,3 +802,3 @@ const baseFactors = factorize(P['n']);

return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) +
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) +
(places * this["n"] % this["d"] > C_ZERO && this["s"] >= C_ZERO ? C_ONE : C_ZERO),

@@ -815,3 +817,3 @@ places);

return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) -
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) -
(places * this["n"] % this["d"] > C_ZERO && this["s"] < C_ZERO ? C_ONE : C_ZERO),

@@ -833,15 +835,15 @@ places);

s >= 0:
round(n / d) = trunc(n / d) + (n % d) / d >= 0.5 ? 1 : 0
= trunc(n / d) + 2(n % d) >= d ? 1 : 0
round(n / d) = ifloor(n / d) + (n % d) / d >= 0.5 ? 1 : 0
= ifloor(n / d) + 2(n % d) >= d ? 1 : 0
s < 0:
round(n / d) =-trunc(n / d) - (n % d) / d > 0.5 ? 1 : 0
=-trunc(n / d) - 2(n % d) > d ? 1 : 0
round(n / d) =-ifloor(n / d) - (n % d) / d > 0.5 ? 1 : 0
=-ifloor(n / d) - 2(n % d) > d ? 1 : 0
=>:
round(s * n / d) = s * trunc(n / d) + s * (C + 2(n % d) > d ? 1 : 0)
round(s * n / d) = s * ifloor(n / d) + s * (C + 2(n % d) > d ? 1 : 0)
where C = s >= 0 ? 1 : 0, to fix the >= for the positve case.
*/
return newFraction(trunc(this["s"] * places * this["n"] / this["d"]) +
return newFraction(ifloor(this["s"] * places * this["n"] / this["d"]) +
this["s"] * ((this["s"] >= C_ZERO ? C_ONE : C_ZERO) + C_TWO * (places * this["n"] % this["d"]) > this["d"] ? C_ONE : C_ZERO),

@@ -871,4 +873,4 @@ places);

// round(n / d) = trunc(n / d) + 2(n % d) >= d ? 1 : 0
let k = trunc(n / d);
// round(n / d) = ifloor(n / d) + 2(n % d) >= d ? 1 : 0
let k = ifloor(n / d);
if (r + r >= d) {

@@ -888,3 +890,4 @@ k++;

parse(a, b);
return !(!(P["n"] * this["d"]) || ((this["n"] * P["d"]) % (P["n"] * this["d"])));
if (P['n'] === C_ZERO) return false;
return (this['n'] * P['d']) % (P['n'] * this['d']) === C_ZERO;
},

@@ -898,4 +901,5 @@

'valueOf': function () {
// Best we can do so far
return Number(this["s"] * this["n"]) / Number(this["d"]);
//if (this['n'] <= MAX_INTEGER && this['d'] <= MAX_INTEGER) {
return Number(this['s'] * this['n']) / Number(this['d']);
//}
},

@@ -908,3 +912,3 @@

**/
'toString': function (dec) {
'toString': function (dec = 15) {

@@ -914,4 +918,2 @@ let N = this["n"];

dec = dec || 15; // 15 = decimal places when no repetition
let cycLen = cycleLen(N, D); // Cycle length

@@ -923,3 +925,3 @@ let cycOff = cycleStart(N, D, cycLen); // Cycle start

// Append integer part
str += trunc(N / D);
str += ifloor(N / D);

@@ -935,3 +937,3 @@ N %= D;

for (let i = cycOff; i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -942,3 +944,3 @@ N *= C_TEN;

for (let i = cycLen; i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -950,3 +952,3 @@ N *= C_TEN;

for (let i = dec; N && i--;) {
str += trunc(N / D);
str += ifloor(N / D);
N %= D;

@@ -964,3 +966,3 @@ N *= C_TEN;

**/
'toFraction': function (showMixed) {
'toFraction': function (showMixed = false) {

@@ -974,3 +976,3 @@ let n = this["n"];

} else {
let whole = trunc(n / d);
const whole = ifloor(n / d);
if (showMixed && whole > C_ZERO) {

@@ -994,3 +996,3 @@ str += whole;

**/
'toLatex': function (showMixed) {
'toLatex': function (showMixed = false) {

@@ -1004,3 +1006,3 @@ let n = this["n"];

} else {
let whole = trunc(n / d);
const whole = ifloor(n / d);
if (showMixed && whole > C_ZERO) {

@@ -1029,18 +1031,21 @@ str += whole;

let b = this['d'];
let res = [];
const res = [];
do {
res.push(trunc(a / b));
let t = a % b;
while (b) {
res.push(ifloor(a / b));
const t = a % b;
a = b;
b = t;
} while (a !== C_ONE);
}
return res;
},
"simplify": function (eps) {
"simplify": function (eps = 1e-3) {
const ieps = BigInt(1 / (eps || 0.001) | 0);
// Continued fractions give best approximations for a max denominator,
// generally outperforming mediants in denominator–accuracy trade-offs.
// Semiconvergents can further reduce the denominator within tolerance.
const ieps = BigInt(Math.ceil(1 / eps));
const thisABS = this['abs']();

@@ -1047,0 +1052,0 @@ const cont = thisABS['toContinued']();

@@ -1136,2 +1136,20 @@ const Fraction = require('fraction.js');

}, {
label: "(-8/27)^(1/3)",
set: [-8, 27],
fn: "pow",
param: [1, 3],
expect: "null"
}, {
label: "(-8/27)^(2/3)",
set: [-8, 27],
fn: "pow",
param: [2, 3],
expect: "null"
}, {
label: "(-32/243)^(5/3)",
set: [-32, 243],
fn: "pow",
param: [5, 3],
expect: "null"
}, {
label: "sqrt(0)",

@@ -1138,0 +1156,0 @@ set: 0,