This question already has answers here:
Calculating pow(a,b) mod n
(14 answers)
Closed 6 years ago.
Is there are trick to get the modulo of big numbers in Javascript. I am getting infinity with modulo(7, 16971, 25777) 7^16971mod25777=NaN
function modulo (n, p, m){
var x = Math.pow(n, p);
var y = m;
var z = x%y;
alert(x);
return z;
}
There's a mathematical "trick" you can use, if you can assume all parameters are integers.
Consider the following modulo operation:
(a*x + y) % x
Obviously, the a*x part can be discarded and the following holds:
(a*x + y) % x = y % x
With that in mind we can assume the big number is just a*x + y, and we can perform the modulo at any stage, and as often as we like, so, to get the result you want, do this:
function modulo (n, p, m){
var result = 1;
while(p--) {
result = (result * n) % m;
}
return result;
}
console.log(modulo(7, 16971, 25777));
JavaScript numbers are stored as 64-bit floats.
Math.pow(7, 16971) is Infinity because the value is too large for that representation. Specifically, it's larger than Number.MAX_VALUE, which is 1.7976931348623157e+308.
The largest safe integer is Math.pow(2, 53) - 1), aka Number.MAX_SAFE_INTEGER.
You can use an arbitrary size integer library like big-integer to work with larger integers:
const result = bigInt(7).modPow(16971, 25777);
console.log(result.value); // 857
JSFiddle
You'll probably want to look into a large number library such as big.js to do this. It has its own mod() function to handle larger numbers and greater floating point precision.
From the manual:
1 % 0.9 // 0.09999999999999998
x = new Big(1)
x.mod(0.9) // '0.1'
Please try this, it should work for you...
<script src="http://peterolson.github.com/BigInteger.js/BigInteger.min.js"></script>
<script>
function modulo(n, p, m) {
var x = bigInt(n).pow(p);
var y = m;
var z = bigInt(x).mod(y);
alert(x);
alert(z);
return z;
}
modulo(7, 16971, 25777);
</script>
Value of X= ( 144157446840451635235083706110907852415749228859252529148906391999766994677256648514596635518338118874745245599504027645569205474259056773767697690363704468632892152795016715055324575445087682781252313005869045568884109150825799944546337893064300709178398146710515468212610079448225972249066488499049225372747076806433631659786194988344294497773759564575000162869574365014937829611100108282508068839769488427218809418476143641444334160948843097387146975458980549194883596975058014553601039150039974922599124812752683319818785474747861041069869797998022819369652619759825244859686407688179575508679861543683676353692931928781365284923967762962761189903683793268647203089135578161089792845634056425105473120490657724974694040110140134504449715061852058159494813855440466218772852172975097582562908895057311050472869260715192269051794091102837753073541384982827121618414372575452344004360364276677087398549812260325448141226947881328515773351976616276417638128022815680053293310617319251468387901625157...56951333749257599033126883342183151178668919812064049965349560466150682525651094508048667165975539000764644172767648163518366194953573817885103167718630743142062623550549541359220427411352708364483389060986844929269143259135008252906461288098421933603373774514126347477000279431329468363160423511545129487503178839098880369937328996412126931687097210220191726087729442555830870326323512951767388505151559227624666317971526350895004302090730198002124799887057180493028281166853990182770936726392403645367304961828645095221020100469965292184204520213166368848723223621651107654075062116217744242552262031457878341343131239324794711518591327361143916482110866686618572491075943511233044928342441933757654662089762470943194596874717623496819342403306038522266428198018364568515908102686200233757394776127456240030822204960242512397946554388855232832783930954979762030089547004776120626513910030444279665047610388454114197939348310563226006027400434616239674784018828580353008938225035036985223336494743), please take a look at output screen below.
Value of Z=(857). please take a look at output screen below.
Related
For example, if my function was called getlowestfraction(), this is what I expect it to do:
getlowestfraction(0.5) // returns 1, 2 or something along the lines of that
Another example:
getlowestfraction(0.125) // returns 1, 8 or something along the lines of that
Using Continued Fractions one can efficiently create a (finite or infinite) sequence of fractions hn/kn that are arbitrary good approximations to a given real number x.
If x is a rational number, the process stops at some point with hn/kn == x. If x is not a rational number, the sequence hn/kn, n = 0, 1, 2, ... converges to x very quickly.
The continued fraction algorithm produces only reduced fractions (nominator and denominator are relatively prime), and the fractions are in
some sense the "best rational approximations" to a given real number.
I am not a JavaScript person (programming in C normally), but I have tried to implement the algorithm with the following JavaScript function. Please forgive me if there are stupid errors. But I have checked the function and it seems to work correctly.
function getlowestfraction(x0) {
var eps = 1.0E-15;
var h, h1, h2, k, k1, k2, a, x;
x = x0;
a = Math.floor(x);
h1 = 1;
k1 = 0;
h = a;
k = 1;
while (x-a > eps*k*k) {
x = 1/(x-a);
a = Math.floor(x);
h2 = h1; h1 = h;
k2 = k1; k1 = k;
h = h2 + a*h1;
k = k2 + a*k1;
}
return h + "/" + k;
}
The loop stops when the rational approximation is exact or has the given precision eps = 1.0E-15. Of course, you can adjust the precision to your needs. (The while condition is derived from the theory of continued fractions.)
Examples (with the number of iterations of the while-loop):
getlowestfraction(0.5) = 1/2 (1 iteration)
getlowestfraction(0.125) = 1/8 (1 iteration)
getlowestfraction(0.1+0.2) = 3/10 (2 iterations)
getlowestfraction(1.0/3.0) = 1/3 (1 iteration)
getlowestfraction(Math.PI) = 80143857/25510582 (12 iterations)
Note that this algorithm gives 1/3 as approximation for x = 1.0/3.0. Repeated multiplication of x by powers of 10 and canceling common factors would give something like 3333333333/10000000000.
Here is an example of different precisions:
With eps = 1.0E-15 you get getlowestfraction(0.142857) = 142857/1000000.
With eps = 1.0E-6 you get getlowestfraction(0.142857) = 1/7.
You could keep multiplying by ten until you have integer values for your numerator and denominator, then use the answers from this question to reduce the fraction to its simplest terms.
Try this program instead:
function toFrac(number) {
var fractional = number % 1;
if (fractional) {
var real = number - fractional;
var exponent = String(fractional).length - 2;
var denominator = Math.pow(10, exponent);
var mantissa = fractional * denominator;
var numerator = real * denominator + mantissa;
var gcd = GCD(numerator, denominator);
denominator /= gcd;
numerator /= gcd;
return [numerator, denominator];
} else return [number, 1];
}
function gcd(numerator, denominator) {
do {
var modulus = numerator % denominator;
numerator = denominator;
denominator = modulus;
} while (modulus);
return numerator;
}
Then you may use it as follows:
var start = new Date;
var PI = toFrac(Math.PI);
var end = new Date;
alert(PI);
alert(PI[0] / PI[1]);
alert(end - start + " ms");
You can see the demo here: http://jsfiddle.net/MZaK9/1/
Was just fiddling around with code, and got the answer myself:
function getlowestfraction (num) {
var i = 1;
var mynum = num;
var retnum = 0;
while (true) {
if (mynum * i % 1 == 0) {
retnum = mynum * i;
break;
}
// For exceptions, tuned down MAX value a bit
if (i > 9000000000000000) {
return false;
}
i++;
}
return retnum + ", " + i;
}
In case anybody needed it.
P.S: I'm not trying to display my expertise or range of knowledge. I actually did spend a long time in JSFiddle trying to figure this out (well not a really long time anyway).
Suppose the number is x = 0 . ( a_1 a_2 ... a_k ) ( a_1 a_2 ... a_k ) .... for simplicity (keep in mind that the first few digits may not fit the repeating pattern, and that we need a way to figure out what k is). If b is the base, then
b ^ k * x - x = ( b ^ k - 1 ) * x
on one hand, but
b ^ k * x - x = ( a_1 a_2 ... a_k )
(exact, ie this is an integer) on the other hand.
So
x = ( a_1 ... a_k ) / ( b ^ k - 1 )
Now you can use Euclid's algorithm to get the gcd and divide it out to get the reduced fraction.
You would still have to figure out how to determine the repeating sequence. There should be an answer to that question. EDIT - one answer: it's the length of \1 if there's a match to the pattern /([0-9]+)\1+$/ (you might want to throw out the last digit before matching bc of rounding). If there's no match, then there's no better "answer" than the "trivial" representation" (x*base^precision/base^precision).
N.B. This answer makes some assumptions on what you expect of an answer, maybe not right for your needs. But it's the "textbook" way of getting reproducing the fraction from a repeating decimal representation - see e.g. here
A very old but a gold question which at the same time an overlooked one. So i will go and mark this popular one as a duplicate with hopes that new people end up at the correct place.
The accepted answer of this question is a gem of the internet. No library that i am aware of uses this magnificient technique and ends up with not wrong but silly rationals. Having said that, the accepted answer is not totally correct due to several issues like;
What exactly is happening there?
Why it still returns '140316103787451/7931944815571' instead of '1769/100' when the input is 17.69?
How do you decide when to stop the while loop?
Now the most important question is, what's happening there and howcome this algorithm is so very efficient.
We must know that any number can also be expressed as a continuous fraction. Say you are given 0.5. You can express it like
1
0 + ___ // the 0 here is in fact Math.floor(0.5)
2 // the 2 here is in fact Math.floor(1/0.5)
So say you are given 2.175 then you end up with
1
2 + _______________ // the 2 here is in fact Math.floor(2.175)
1
5 + ___________ // the 5 here is in fact Math.floor(1/0.175 = 5.714285714285714)
1
1 + _______ // the 1 here is in fact Math.floor(1/0.714285714285714 = 1.4)
1
2 + ___ // the 2 here is in fact Math.floor(1/0.4 = 2.5)
2 // the 2 here is in fact Math.floor(1/0.5)
We now have our continued fraction coefficients like [2;5,1,2,2] for 2.175. However the beauty of this algorithm lies behind how it calculates the approximation at once when we calculate the next continued fraction constant without requiring any further calculations. At this very moment we can compare the currently reached result with the given value and decide to stop or iterate once more.
So far so good however it still doesn't make sense right? Let us go with another solid example. Input value is 3.686635944700461. Now we are going to approach this from Infinity and very quickly converge to the result. So our first rational is 1/0 aka Infinity. We denote this as a fraction with a numerator p as 1 and denominator q as 0 aka 1/0. The previous approximation would be p_/q_ for the next stage. Let us make it 0 to start with. So p_ is 0 and q_ is 1.
The important part is, once we know the two previous approximations, (p, q, p_ and q_) we can then calculate the next coefficient m and also the next p and q to compare with the input. Calculating the coefficient m is as simple as Math.floor(x_) whereas x_ is reciprocal of the next floating part. The next approximation p/q would then be (m * p + p_)/(m * q + q_) and the next p_/q_ would be the previous p/q. (Theorem 2.4 # this paper)
Now given above information any decent programmer can easily resolve the following snippet. For curious, 3.686635944700461 is 800/217 and gets calculated in just 5 iterations by the below code.
function toRational(x){
var m = Math.floor(x),
x_ = 1/(x-m),
p_ = 1,
q_ = 0,
p = m,
q = 1;
if (x === m) return {n:p,d:q};
while (Math.abs(x - p/q) > Number.EPSILON){
m = Math.floor(x_);
x_ = 1/(x_-m);
[p_, q_, p, q] = [p, q, m*p+p_, m*q+q_];
}
return isNaN(x) ? NaN : {n:p,d:q};
}
Under practical considerations it would be ideal to store the coefficients in the fraction object as well so that in future you may use them to perform CFA (Continuous Fraction Arithmetics) among rationals. This way you may avoid huge integers and possible BigInt usage by staying in the CF domain to perform invertion, negation, addition and multiplication operations. Sadly, CFA is a very overlooked topic but it helps us to avoid double precision errors when doing cascaded arithmetic operations on the rational type values.
So I was calculating last ten digit of the series :
1^1 + 2^2 + 3^3 + ... + 1000^1000
But I keep getting NaN as a result.
Code:
function myFunction() {
var i, x, a, sum = 0; {
for (i = 1; i <= 1000; i++) {
var a = Math.pow(i, i);
sum += a;
}
var x = sum;
var y = x % 10000000000;
}
document.getElementById("demo").innerHTML = y;
}
<p>Click the button to demontrate </p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
Math.pow(1000, 1000)
Thats a very very huge number, (3000 zeros), so javascript can't handle it, thats why the above results in Infinity. And the modulo of an infinite number cannot be determined, therefore the result is Not A Number.
You have an Infinity value - try the code below :
function myFunction() {
var i, x, a, sum = 0; {
for (i = 1; i <= 1000; i++) {
var a = Math.pow(i, i);
if(a!=Infinity)sum += a;
}
var x = sum;
var y = x % 10000000000;
document.getElementById("demo").innerHTML = y;
}
Javascript uses 64-bit floating point numbers for everything. The max value of one of those is about 1.8 × 10^308, which is quite a bit smaller than your 1000^1000 value. As a consequence, since the number it's trying to calculate can't fit into a "number"-type variable, Javascript returns NaN and leaves it at that.
Number.MAX_VALUE is the maximum number available.
Otherwise you have to use some library for example: https://mikemcl.github.io/bignumber.js/
Explanation
Big Ints (greater than (2^31 - 1) as #suhas explained) are not currently supported in JS, however there is a TC39 draft currently in stage 3 (candidate).
Solution
In the meantime, use a library such as this one.
As #jonas-w correctly pointed out, your specific problem is trying to take the modulo of an infinite number. infinity % anyNumber yields NaN.
In addition, you need to understand that floating-point values use scientific notation. That means that for large numbers, all of your significant digits (53 for IEEE 754 double-precision, which is what JavaScript uses) are at the upper end of the value, yet your modulo is examining the lower end.
For example, 1.1×10^6 is 1,100,000, and 1.2×10^6 is 1,200,000. Getting the % 100 is pointless, as both yield 0.
What are you trying to accomplish with this code?
I am trying to make an RSA like encryption program. Therefore I need to perform a calculation 1069^1099. The problem is that the result of that calculation is infinity according to Javascript. Is there any way around this problem?
var n = 23 * 83;
var e = 87;
var d = 1099;
var m = 1069;
var m = m**d % n; //Result NaN because m**d = infinity
If you're just developing a toy RSA cipher that doesn't use huge prime numbers, then you can implement modular exponentation as follows:
function modexp(base, exponent, modulus) {
var result = 1;
while (exponent) {
if (exponent & 1) {
result = (result * base) % modulus;
}
base = (base * base) % modulus;
exponent >>= 1;
}
return result;
}
The Wikipedia article has a detailed description, but what it basically does is split xe into the product of x raised to the power of numbers corresponding to each set bit in the binary representation of e. For example, x13 == x8 × x4 × x1 (because 1310 == 11012). This can be calculated efficiently by squaring x at each step, and applying the modulus after each calculation so that the numbers don't get too large.
As others have said, you'll need a big number library to handle real-world RSA keys.
I use bignum to circumvent the limits of large numbers in js.
https://www.npmjs.com/package/bignum
Your code would look something like this:
var result = bignum(m).pow(d).mod(n)
// or more consicely
var result = bignum(m).powm(d, n)
I need to perform modular exponentiation on quite large numbers on both python3 and javascript. I have functions that do the task, but they give me different outputs.
Python (all of the three work in the same way):
pow(176672119508, 55, 200000023499)
def expmod_iter(a,b,c):
x = 1
while(b>0):
if(b&1==1): x = (x*a)%c
a=(a*a)%c
b >>= 1
return x%c
def pow_mod(x, y, z):
number = 1
while y:
if y & 1:
number = number * x % z
y >>= 1
x = x * x % z
return number
# The result is always 124912252967
and now JavaScript (both functions work in the same way):
function powMod(x, y, z) {
let number = 1;
while (y) {
if (y & 1) {
number = number * x % z;
}
y >>= 1;
x = x * x % z;
}
return number;
}
function expmod_iter(a, b, c) {
let x = 1;
while (b > 0) {
if (b & 1 === 1) {
x = (x * a) % c;
}
a = (a * a) % c;
b >>= 1
}
return x % c;
}
console.log(powMod(176672119508, 55, 200000023499));
console.log(expmod_iter(176672119508, 55, 200000023499));
// The result is always 138693107570
And moreover, when I used this service with my numbers, I also got 138693107570.
Why does this happen? I'm not even sure what variant is correct now. However, on smaller numbers the functions give identical results.
Is it possible to somehow get the same result from the functions? It doesn't even matter that much that the result is mathematically correct, the results should be at least the same.
Could you please explain why this happens? Is it the function design? To me, functions on both languages seem to be identical.
Is there a way to get the same result from functions of both languages?
Python's result is correct.
Python uses an arbitrary-precision integer representation, while Javascript stores all numbers as IEEE754 64-bit floating point (and temporarily coerces them to 32-bit integers for bitwise operations). This means that for large integers, the Javascript code starts losing precision, while the Python code maintains the exact values of all results throughout the calculation.
If you want to handle large integers exactly in Javascript, you will need to use an appropriate library. Alternatively, you say you don't care much about the result being correct. That is a really weird thing to not care about, but if you really feel that way:
# Python
def wrongpow(a, b, c):
return 0
// Javascript
function wrongpow(a, b, c) {
return 0;
}
For example, if my function was called getlowestfraction(), this is what I expect it to do:
getlowestfraction(0.5) // returns 1, 2 or something along the lines of that
Another example:
getlowestfraction(0.125) // returns 1, 8 or something along the lines of that
Using Continued Fractions one can efficiently create a (finite or infinite) sequence of fractions hn/kn that are arbitrary good approximations to a given real number x.
If x is a rational number, the process stops at some point with hn/kn == x. If x is not a rational number, the sequence hn/kn, n = 0, 1, 2, ... converges to x very quickly.
The continued fraction algorithm produces only reduced fractions (nominator and denominator are relatively prime), and the fractions are in
some sense the "best rational approximations" to a given real number.
I am not a JavaScript person (programming in C normally), but I have tried to implement the algorithm with the following JavaScript function. Please forgive me if there are stupid errors. But I have checked the function and it seems to work correctly.
function getlowestfraction(x0) {
var eps = 1.0E-15;
var h, h1, h2, k, k1, k2, a, x;
x = x0;
a = Math.floor(x);
h1 = 1;
k1 = 0;
h = a;
k = 1;
while (x-a > eps*k*k) {
x = 1/(x-a);
a = Math.floor(x);
h2 = h1; h1 = h;
k2 = k1; k1 = k;
h = h2 + a*h1;
k = k2 + a*k1;
}
return h + "/" + k;
}
The loop stops when the rational approximation is exact or has the given precision eps = 1.0E-15. Of course, you can adjust the precision to your needs. (The while condition is derived from the theory of continued fractions.)
Examples (with the number of iterations of the while-loop):
getlowestfraction(0.5) = 1/2 (1 iteration)
getlowestfraction(0.125) = 1/8 (1 iteration)
getlowestfraction(0.1+0.2) = 3/10 (2 iterations)
getlowestfraction(1.0/3.0) = 1/3 (1 iteration)
getlowestfraction(Math.PI) = 80143857/25510582 (12 iterations)
Note that this algorithm gives 1/3 as approximation for x = 1.0/3.0. Repeated multiplication of x by powers of 10 and canceling common factors would give something like 3333333333/10000000000.
Here is an example of different precisions:
With eps = 1.0E-15 you get getlowestfraction(0.142857) = 142857/1000000.
With eps = 1.0E-6 you get getlowestfraction(0.142857) = 1/7.
You could keep multiplying by ten until you have integer values for your numerator and denominator, then use the answers from this question to reduce the fraction to its simplest terms.
Try this program instead:
function toFrac(number) {
var fractional = number % 1;
if (fractional) {
var real = number - fractional;
var exponent = String(fractional).length - 2;
var denominator = Math.pow(10, exponent);
var mantissa = fractional * denominator;
var numerator = real * denominator + mantissa;
var gcd = GCD(numerator, denominator);
denominator /= gcd;
numerator /= gcd;
return [numerator, denominator];
} else return [number, 1];
}
function gcd(numerator, denominator) {
do {
var modulus = numerator % denominator;
numerator = denominator;
denominator = modulus;
} while (modulus);
return numerator;
}
Then you may use it as follows:
var start = new Date;
var PI = toFrac(Math.PI);
var end = new Date;
alert(PI);
alert(PI[0] / PI[1]);
alert(end - start + " ms");
You can see the demo here: http://jsfiddle.net/MZaK9/1/
Was just fiddling around with code, and got the answer myself:
function getlowestfraction (num) {
var i = 1;
var mynum = num;
var retnum = 0;
while (true) {
if (mynum * i % 1 == 0) {
retnum = mynum * i;
break;
}
// For exceptions, tuned down MAX value a bit
if (i > 9000000000000000) {
return false;
}
i++;
}
return retnum + ", " + i;
}
In case anybody needed it.
P.S: I'm not trying to display my expertise or range of knowledge. I actually did spend a long time in JSFiddle trying to figure this out (well not a really long time anyway).
Suppose the number is x = 0 . ( a_1 a_2 ... a_k ) ( a_1 a_2 ... a_k ) .... for simplicity (keep in mind that the first few digits may not fit the repeating pattern, and that we need a way to figure out what k is). If b is the base, then
b ^ k * x - x = ( b ^ k - 1 ) * x
on one hand, but
b ^ k * x - x = ( a_1 a_2 ... a_k )
(exact, ie this is an integer) on the other hand.
So
x = ( a_1 ... a_k ) / ( b ^ k - 1 )
Now you can use Euclid's algorithm to get the gcd and divide it out to get the reduced fraction.
You would still have to figure out how to determine the repeating sequence. There should be an answer to that question. EDIT - one answer: it's the length of \1 if there's a match to the pattern /([0-9]+)\1+$/ (you might want to throw out the last digit before matching bc of rounding). If there's no match, then there's no better "answer" than the "trivial" representation" (x*base^precision/base^precision).
N.B. This answer makes some assumptions on what you expect of an answer, maybe not right for your needs. But it's the "textbook" way of getting reproducing the fraction from a repeating decimal representation - see e.g. here
A very old but a gold question which at the same time an overlooked one. So i will go and mark this popular one as a duplicate with hopes that new people end up at the correct place.
The accepted answer of this question is a gem of the internet. No library that i am aware of uses this magnificient technique and ends up with not wrong but silly rationals. Having said that, the accepted answer is not totally correct due to several issues like;
What exactly is happening there?
Why it still returns '140316103787451/7931944815571' instead of '1769/100' when the input is 17.69?
How do you decide when to stop the while loop?
Now the most important question is, what's happening there and howcome this algorithm is so very efficient.
We must know that any number can also be expressed as a continuous fraction. Say you are given 0.5. You can express it like
1
0 + ___ // the 0 here is in fact Math.floor(0.5)
2 // the 2 here is in fact Math.floor(1/0.5)
So say you are given 2.175 then you end up with
1
2 + _______________ // the 2 here is in fact Math.floor(2.175)
1
5 + ___________ // the 5 here is in fact Math.floor(1/0.175 = 5.714285714285714)
1
1 + _______ // the 1 here is in fact Math.floor(1/0.714285714285714 = 1.4)
1
2 + ___ // the 2 here is in fact Math.floor(1/0.4 = 2.5)
2 // the 2 here is in fact Math.floor(1/0.5)
We now have our continued fraction coefficients like [2;5,1,2,2] for 2.175. However the beauty of this algorithm lies behind how it calculates the approximation at once when we calculate the next continued fraction constant without requiring any further calculations. At this very moment we can compare the currently reached result with the given value and decide to stop or iterate once more.
So far so good however it still doesn't make sense right? Let us go with another solid example. Input value is 3.686635944700461. Now we are going to approach this from Infinity and very quickly converge to the result. So our first rational is 1/0 aka Infinity. We denote this as a fraction with a numerator p as 1 and denominator q as 0 aka 1/0. The previous approximation would be p_/q_ for the next stage. Let us make it 0 to start with. So p_ is 0 and q_ is 1.
The important part is, once we know the two previous approximations, (p, q, p_ and q_) we can then calculate the next coefficient m and also the next p and q to compare with the input. Calculating the coefficient m is as simple as Math.floor(x_) whereas x_ is reciprocal of the next floating part. The next approximation p/q would then be (m * p + p_)/(m * q + q_) and the next p_/q_ would be the previous p/q. (Theorem 2.4 # this paper)
Now given above information any decent programmer can easily resolve the following snippet. For curious, 3.686635944700461 is 800/217 and gets calculated in just 5 iterations by the below code.
function toRational(x){
var m = Math.floor(x),
x_ = 1/(x-m),
p_ = 1,
q_ = 0,
p = m,
q = 1;
if (x === m) return {n:p,d:q};
while (Math.abs(x - p/q) > Number.EPSILON){
m = Math.floor(x_);
x_ = 1/(x_-m);
[p_, q_, p, q] = [p, q, m*p+p_, m*q+q_];
}
return isNaN(x) ? NaN : {n:p,d:q};
}
Under practical considerations it would be ideal to store the coefficients in the fraction object as well so that in future you may use them to perform CFA (Continuous Fraction Arithmetics) among rationals. This way you may avoid huge integers and possible BigInt usage by staying in the CF domain to perform invertion, negation, addition and multiplication operations. Sadly, CFA is a very overlooked topic but it helps us to avoid double precision errors when doing cascaded arithmetic operations on the rational type values.