bigfraction.js (21076B)
1 /** 2 * @license Fraction.js v4.2.0 23/05/2021 3 * https://www.xarg.org/2014/03/rational-numbers-in-javascript/ 4 * 5 * Copyright (c) 2021, Robert Eisele (robert@xarg.org) 6 * Dual licensed under the MIT or GPL Version 2 licenses. 7 **/ 8 9 10 /** 11 * 12 * This class offers the possibility to calculate fractions. 13 * You can pass a fraction in different formats. Either as array, as double, as string or as an integer. 14 * 15 * Array/Object form 16 * [ 0 => <nominator>, 1 => <denominator> ] 17 * [ n => <nominator>, d => <denominator> ] 18 * 19 * Integer form 20 * - Single integer value 21 * 22 * Double form 23 * - Single double value 24 * 25 * String form 26 * 123.456 - a simple double 27 * 123/456 - a string fraction 28 * 123.'456' - a double with repeating decimal places 29 * 123.(456) - synonym 30 * 123.45'6' - a double with repeating last place 31 * 123.45(6) - synonym 32 * 33 * Example: 34 * 35 * let f = new Fraction("9.4'31'"); 36 * f.mul([-4, 3]).div(4.9); 37 * 38 */ 39 40 (function(root) { 41 42 "use strict"; 43 44 // Set Identity function to downgrade BigInt to Number if needed 45 if (!BigInt) BigInt = function(n) { if (isNaN(n)) throw new Error(""); return n; }; 46 47 const C_ONE = BigInt(1); 48 const C_ZERO = BigInt(0); 49 const C_TEN = BigInt(10); 50 const C_TWO = BigInt(2); 51 const C_FIVE = BigInt(5); 52 53 // Maximum search depth for cyclic rational numbers. 2000 should be more than enough. 54 // Example: 1/7 = 0.(142857) has 6 repeating decimal places. 55 // If MAX_CYCLE_LEN gets reduced, long cycles will not be detected and toString() only gets the first 10 digits 56 const MAX_CYCLE_LEN = 2000; 57 58 // Parsed data to avoid calling "new" all the time 59 const P = { 60 "s": C_ONE, 61 "n": C_ZERO, 62 "d": C_ONE 63 }; 64 65 function assign(n, s) { 66 67 try { 68 n = BigInt(n); 69 } catch (e) { 70 throw Fraction['InvalidParameter']; 71 } 72 return n * s; 73 } 74 75 // Creates a new Fraction internally without the need of the bulky constructor 76 function newFraction(n, d) { 77 78 if (d === C_ZERO) { 79 throw Fraction['DivisionByZero']; 80 } 81 82 const f = Object.create(Fraction.prototype); 83 f["s"] = n < C_ZERO ? -C_ONE : C_ONE; 84 85 n = n < C_ZERO ? -n : n; 86 87 const a = gcd(n, d); 88 89 f["n"] = n / a; 90 f["d"] = d / a; 91 return f; 92 } 93 94 function factorize(num) { 95 96 const factors = {}; 97 98 let n = num; 99 let i = C_TWO; 100 let s = C_FIVE - C_ONE; 101 102 while (s <= n) { 103 104 while (n % i === C_ZERO) { 105 n/= i; 106 factors[i] = (factors[i] || C_ZERO) + C_ONE; 107 } 108 s+= C_ONE + C_TWO * i++; 109 } 110 111 if (n !== num) { 112 if (n > 1) 113 factors[n] = (factors[n] || C_ZERO) + C_ONE; 114 } else { 115 factors[num] = (factors[num] || C_ZERO) + C_ONE; 116 } 117 return factors; 118 } 119 120 const parse = function(p1, p2) { 121 122 let n = C_ZERO, d = C_ONE, s = C_ONE; 123 124 if (p1 === undefined || p1 === null) { 125 /* void */ 126 } else if (p2 !== undefined) { 127 n = BigInt(p1); 128 d = BigInt(p2); 129 s = n * d; 130 131 if (n % C_ONE !== C_ZERO || d % C_ONE !== C_ZERO) { 132 throw Fraction['NonIntegerParameter']; 133 } 134 135 } else if (typeof p1 === "object") { 136 if ("d" in p1 && "n" in p1) { 137 n = BigInt(p1["n"]); 138 d = BigInt(p1["d"]); 139 if ("s" in p1) 140 n*= BigInt(p1["s"]); 141 } else if (0 in p1) { 142 n = BigInt(p1[0]); 143 if (1 in p1) 144 d = BigInt(p1[1]); 145 } else if (p1 instanceof BigInt) { 146 n = BigInt(p1); 147 } else { 148 throw Fraction['InvalidParameter']; 149 } 150 s = n * d; 151 } else if (typeof p1 === "bigint") { 152 n = p1; 153 s = p1; 154 d = BigInt(1); 155 } else if (typeof p1 === "number") { 156 157 if (isNaN(p1)) { 158 throw Fraction['InvalidParameter']; 159 } 160 161 if (p1 < 0) { 162 s = -C_ONE; 163 p1 = -p1; 164 } 165 166 if (p1 % 1 === 0) { 167 n = BigInt(p1); 168 } else if (p1 > 0) { // check for != 0, scale would become NaN (log(0)), which converges really slow 169 170 let z = 1; 171 172 let A = 0, B = 1; 173 let C = 1, D = 1; 174 175 let N = 10000000; 176 177 if (p1 >= 1) { 178 z = 10 ** Math.floor(1 + Math.log10(p1)); 179 p1/= z; 180 } 181 182 // Using Farey Sequences 183 184 while (B <= N && D <= N) { 185 let M = (A + C) / (B + D); 186 187 if (p1 === M) { 188 if (B + D <= N) { 189 n = A + C; 190 d = B + D; 191 } else if (D > B) { 192 n = C; 193 d = D; 194 } else { 195 n = A; 196 d = B; 197 } 198 break; 199 200 } else { 201 202 if (p1 > M) { 203 A+= C; 204 B+= D; 205 } else { 206 C+= A; 207 D+= B; 208 } 209 210 if (B > N) { 211 n = C; 212 d = D; 213 } else { 214 n = A; 215 d = B; 216 } 217 } 218 } 219 n = BigInt(n) * BigInt(z); 220 d = BigInt(d); 221 222 } 223 224 } else if (typeof p1 === "string") { 225 226 let ndx = 0; 227 228 let v = C_ZERO, w = C_ZERO, x = C_ZERO, y = C_ONE, z = C_ONE; 229 230 let match = p1.match(/\d+|./g); 231 232 if (match === null) 233 throw Fraction['InvalidParameter']; 234 235 if (match[ndx] === '-') {// Check for minus sign at the beginning 236 s = -C_ONE; 237 ndx++; 238 } else if (match[ndx] === '+') {// Check for plus sign at the beginning 239 ndx++; 240 } 241 242 if (match.length === ndx + 1) { // Check if it's just a simple number "1234" 243 w = assign(match[ndx++], s); 244 } else if (match[ndx + 1] === '.' || match[ndx] === '.') { // Check if it's a decimal number 245 246 if (match[ndx] !== '.') { // Handle 0.5 and .5 247 v = assign(match[ndx++], s); 248 } 249 ndx++; 250 251 // Check for decimal places 252 if (ndx + 1 === match.length || match[ndx + 1] === '(' && match[ndx + 3] === ')' || match[ndx + 1] === "'" && match[ndx + 3] === "'") { 253 w = assign(match[ndx], s); 254 y = C_TEN ** BigInt(match[ndx].length); 255 ndx++; 256 } 257 258 // Check for repeating places 259 if (match[ndx] === '(' && match[ndx + 2] === ')' || match[ndx] === "'" && match[ndx + 2] === "'") { 260 x = assign(match[ndx + 1], s); 261 z = C_TEN ** BigInt(match[ndx + 1].length) - C_ONE; 262 ndx+= 3; 263 } 264 265 } else if (match[ndx + 1] === '/' || match[ndx + 1] === ':') { // Check for a simple fraction "123/456" or "123:456" 266 w = assign(match[ndx], s); 267 y = assign(match[ndx + 2], C_ONE); 268 ndx+= 3; 269 } else if (match[ndx + 3] === '/' && match[ndx + 1] === ' ') { // Check for a complex fraction "123 1/2" 270 v = assign(match[ndx], s); 271 w = assign(match[ndx + 2], s); 272 y = assign(match[ndx + 4], C_ONE); 273 ndx+= 5; 274 } 275 276 if (match.length <= ndx) { // Check for more tokens on the stack 277 d = y * z; 278 s = /* void */ 279 n = x + d * v + z * w; 280 } else { 281 throw Fraction['InvalidParameter']; 282 } 283 284 } else { 285 throw Fraction['InvalidParameter']; 286 } 287 288 if (d === C_ZERO) { 289 throw Fraction['DivisionByZero']; 290 } 291 292 P["s"] = s < C_ZERO ? -C_ONE : C_ONE; 293 P["n"] = n < C_ZERO ? -n : n; 294 P["d"] = d < C_ZERO ? -d : d; 295 }; 296 297 function modpow(b, e, m) { 298 299 let r = C_ONE; 300 for (; e > C_ZERO; b = (b * b) % m, e >>= C_ONE) { 301 302 if (e & C_ONE) { 303 r = (r * b) % m; 304 } 305 } 306 return r; 307 } 308 309 function cycleLen(n, d) { 310 311 for (; d % C_TWO === C_ZERO; 312 d/= C_TWO) { 313 } 314 315 for (; d % C_FIVE === C_ZERO; 316 d/= C_FIVE) { 317 } 318 319 if (d === C_ONE) // Catch non-cyclic numbers 320 return C_ZERO; 321 322 // If we would like to compute really large numbers quicker, we could make use of Fermat's little theorem: 323 // 10^(d-1) % d == 1 324 // However, we don't need such large numbers and MAX_CYCLE_LEN should be the capstone, 325 // as we want to translate the numbers to strings. 326 327 let rem = C_TEN % d; 328 let t = 1; 329 330 for (; rem !== C_ONE; t++) { 331 rem = rem * C_TEN % d; 332 333 if (t > MAX_CYCLE_LEN) 334 return C_ZERO; // Returning 0 here means that we don't print it as a cyclic number. It's likely that the answer is `d-1` 335 } 336 return BigInt(t); 337 } 338 339 function cycleStart(n, d, len) { 340 341 let rem1 = C_ONE; 342 let rem2 = modpow(C_TEN, len, d); 343 344 for (let t = 0; t < 300; t++) { // s < ~log10(Number.MAX_VALUE) 345 // Solve 10^s == 10^(s+t) (mod d) 346 347 if (rem1 === rem2) 348 return BigInt(t); 349 350 rem1 = rem1 * C_TEN % d; 351 rem2 = rem2 * C_TEN % d; 352 } 353 return 0; 354 } 355 356 function gcd(a, b) { 357 358 if (!a) 359 return b; 360 if (!b) 361 return a; 362 363 while (1) { 364 a%= b; 365 if (!a) 366 return b; 367 b%= a; 368 if (!b) 369 return a; 370 } 371 } 372 373 /** 374 * Module constructor 375 * 376 * @constructor 377 * @param {number|Fraction=} a 378 * @param {number=} b 379 */ 380 function Fraction(a, b) { 381 382 parse(a, b); 383 384 if (this instanceof Fraction) { 385 a = gcd(P["d"], P["n"]); // Abuse a 386 this["s"] = P["s"]; 387 this["n"] = P["n"] / a; 388 this["d"] = P["d"] / a; 389 } else { 390 return newFraction(P['s'] * P['n'], P['d']); 391 } 392 } 393 394 Fraction['DivisionByZero'] = new Error("Division by Zero"); 395 Fraction['InvalidParameter'] = new Error("Invalid argument"); 396 Fraction['NonIntegerParameter'] = new Error("Parameters must be integer"); 397 398 Fraction.prototype = { 399 400 "s": C_ONE, 401 "n": C_ZERO, 402 "d": C_ONE, 403 404 /** 405 * Calculates the absolute value 406 * 407 * Ex: new Fraction(-4).abs() => 4 408 **/ 409 "abs": function() { 410 411 return newFraction(this["n"], this["d"]); 412 }, 413 414 /** 415 * Inverts the sign of the current fraction 416 * 417 * Ex: new Fraction(-4).neg() => 4 418 **/ 419 "neg": function() { 420 421 return newFraction(-this["s"] * this["n"], this["d"]); 422 }, 423 424 /** 425 * Adds two rational numbers 426 * 427 * Ex: new Fraction({n: 2, d: 3}).add("14.9") => 467 / 30 428 **/ 429 "add": function(a, b) { 430 431 parse(a, b); 432 return newFraction( 433 this["s"] * this["n"] * P["d"] + P["s"] * this["d"] * P["n"], 434 this["d"] * P["d"] 435 ); 436 }, 437 438 /** 439 * Subtracts two rational numbers 440 * 441 * Ex: new Fraction({n: 2, d: 3}).add("14.9") => -427 / 30 442 **/ 443 "sub": function(a, b) { 444 445 parse(a, b); 446 return newFraction( 447 this["s"] * this["n"] * P["d"] - P["s"] * this["d"] * P["n"], 448 this["d"] * P["d"] 449 ); 450 }, 451 452 /** 453 * Multiplies two rational numbers 454 * 455 * Ex: new Fraction("-17.(345)").mul(3) => 5776 / 111 456 **/ 457 "mul": function(a, b) { 458 459 parse(a, b); 460 return newFraction( 461 this["s"] * P["s"] * this["n"] * P["n"], 462 this["d"] * P["d"] 463 ); 464 }, 465 466 /** 467 * Divides two rational numbers 468 * 469 * Ex: new Fraction("-17.(345)").inverse().div(3) 470 **/ 471 "div": function(a, b) { 472 473 parse(a, b); 474 return newFraction( 475 this["s"] * P["s"] * this["n"] * P["d"], 476 this["d"] * P["n"] 477 ); 478 }, 479 480 /** 481 * Clones the actual object 482 * 483 * Ex: new Fraction("-17.(345)").clone() 484 **/ 485 "clone": function() { 486 return newFraction(this['s'] * this['n'], this['d']); 487 }, 488 489 /** 490 * Calculates the modulo of two rational numbers - a more precise fmod 491 * 492 * Ex: new Fraction('4.(3)').mod([7, 8]) => (13/3) % (7/8) = (5/6) 493 **/ 494 "mod": function(a, b) { 495 496 if (a === undefined) { 497 return newFraction(this["s"] * this["n"] % this["d"], C_ONE); 498 } 499 500 parse(a, b); 501 if (0 === P["n"] && 0 === this["d"]) { 502 throw Fraction['DivisionByZero']; 503 } 504 505 /* 506 * First silly attempt, kinda slow 507 * 508 return that["sub"]({ 509 "n": num["n"] * Math.floor((this.n / this.d) / (num.n / num.d)), 510 "d": num["d"], 511 "s": this["s"] 512 });*/ 513 514 /* 515 * New attempt: a1 / b1 = a2 / b2 * q + r 516 * => b2 * a1 = a2 * b1 * q + b1 * b2 * r 517 * => (b2 * a1 % a2 * b1) / (b1 * b2) 518 */ 519 return newFraction( 520 this["s"] * (P["d"] * this["n"]) % (P["n"] * this["d"]), 521 P["d"] * this["d"] 522 ); 523 }, 524 525 /** 526 * Calculates the fractional gcd of two rational numbers 527 * 528 * Ex: new Fraction(5,8).gcd(3,7) => 1/56 529 */ 530 "gcd": function(a, b) { 531 532 parse(a, b); 533 534 // gcd(a / b, c / d) = gcd(a, c) / lcm(b, d) 535 536 return newFraction(gcd(P["n"], this["n"]) * gcd(P["d"], this["d"]), P["d"] * this["d"]); 537 }, 538 539 /** 540 * Calculates the fractional lcm of two rational numbers 541 * 542 * Ex: new Fraction(5,8).lcm(3,7) => 15 543 */ 544 "lcm": function(a, b) { 545 546 parse(a, b); 547 548 // lcm(a / b, c / d) = lcm(a, c) / gcd(b, d) 549 550 if (P["n"] === C_ZERO && this["n"] === C_ZERO) { 551 return newFraction(C_ZERO, C_ONE); 552 } 553 return newFraction(P["n"] * this["n"], gcd(P["n"], this["n"]) * gcd(P["d"], this["d"])); 554 }, 555 556 /** 557 * Gets the inverse of the fraction, means numerator and denominator are exchanged 558 * 559 * Ex: new Fraction([-3, 4]).inverse() => -4 / 3 560 **/ 561 "inverse": function() { 562 return newFraction(this["s"] * this["d"], this["n"]); 563 }, 564 565 /** 566 * Calculates the fraction to some integer exponent 567 * 568 * Ex: new Fraction(-1,2).pow(-3) => -8 569 */ 570 "pow": function(a, b) { 571 572 parse(a, b); 573 574 // Trivial case when exp is an integer 575 576 if (P['d'] === C_ONE) { 577 578 if (P['s'] < C_ZERO) { 579 return newFraction((this['s'] * this["d"]) ** P['n'], this["n"] ** P['n']); 580 } else { 581 return newFraction((this['s'] * this["n"]) ** P['n'], this["d"] ** P['n']); 582 } 583 } 584 585 // Negative roots become complex 586 // (-a/b)^(c/d) = x 587 // <=> (-1)^(c/d) * (a/b)^(c/d) = x 588 // <=> (cos(pi) + i*sin(pi))^(c/d) * (a/b)^(c/d) = x 589 // <=> (cos(c*pi/d) + i*sin(c*pi/d)) * (a/b)^(c/d) = x # DeMoivre's formula 590 // From which follows that only for c=0 the root is non-complex 591 if (this['s'] < C_ZERO) return null; 592 593 // Now prime factor n and d 594 let N = factorize(this['n']); 595 let D = factorize(this['d']); 596 597 // Exponentiate and take root for n and d individually 598 let n = C_ONE; 599 let d = C_ONE; 600 for (let k in N) { 601 if (k === '1') continue; 602 if (k === '0') { 603 n = C_ZERO; 604 break; 605 } 606 N[k]*= P['n']; 607 608 if (N[k] % P['d'] === C_ZERO) { 609 N[k]/= P['d']; 610 } else return null; 611 n*= BigInt(k) ** N[k]; 612 } 613 614 for (let k in D) { 615 if (k === '1') continue; 616 D[k]*= P['n']; 617 618 if (D[k] % P['d'] === C_ZERO) { 619 D[k]/= P['d']; 620 } else return null; 621 d*= BigInt(k) ** D[k]; 622 } 623 624 if (P['s'] < C_ZERO) { 625 return newFraction(d, n); 626 } 627 return newFraction(n, d); 628 }, 629 630 /** 631 * Check if two rational numbers are the same 632 * 633 * Ex: new Fraction(19.6).equals([98, 5]); 634 **/ 635 "equals": function(a, b) { 636 637 parse(a, b); 638 return this["s"] * this["n"] * P["d"] === P["s"] * P["n"] * this["d"]; // Same as compare() === 0 639 }, 640 641 /** 642 * Check if two rational numbers are the same 643 * 644 * Ex: new Fraction(19.6).equals([98, 5]); 645 **/ 646 "compare": function(a, b) { 647 648 parse(a, b); 649 let t = (this["s"] * this["n"] * P["d"] - P["s"] * P["n"] * this["d"]); 650 651 return (C_ZERO < t) - (t < C_ZERO); 652 }, 653 654 /** 655 * Calculates the ceil of a rational number 656 * 657 * Ex: new Fraction('4.(3)').ceil() => (5 / 1) 658 **/ 659 "ceil": function(places) { 660 661 places = C_TEN ** BigInt(places || 0); 662 663 return newFraction(this["s"] * places * this["n"] / this["d"] + 664 (places * this["n"] % this["d"] > C_ZERO && this["s"] >= C_ZERO ? C_ONE : C_ZERO), 665 places); 666 }, 667 668 /** 669 * Calculates the floor of a rational number 670 * 671 * Ex: new Fraction('4.(3)').floor() => (4 / 1) 672 **/ 673 "floor": function(places) { 674 675 places = C_TEN ** BigInt(places || 0); 676 677 return newFraction(this["s"] * places * this["n"] / this["d"] - 678 (places * this["n"] % this["d"] > C_ZERO && this["s"] < C_ZERO ? C_ONE : C_ZERO), 679 places); 680 }, 681 682 /** 683 * Rounds a rational numbers 684 * 685 * Ex: new Fraction('4.(3)').round() => (4 / 1) 686 **/ 687 "round": function(places) { 688 689 places = C_TEN ** BigInt(places || 0); 690 691 /* Derivation: 692 693 s >= 0: 694 round(n / d) = trunc(n / d) + (n % d) / d >= 0.5 ? 1 : 0 695 = trunc(n / d) + 2(n % d) >= d ? 1 : 0 696 s < 0: 697 round(n / d) =-trunc(n / d) - (n % d) / d > 0.5 ? 1 : 0 698 =-trunc(n / d) - 2(n % d) > d ? 1 : 0 699 700 =>: 701 702 round(s * n / d) = s * trunc(n / d) + s * (C + 2(n % d) > d ? 1 : 0) 703 where C = s >= 0 ? 1 : 0, to fix the >= for the positve case. 704 */ 705 706 return newFraction(this["s"] * places * this["n"] / this["d"] + 707 this["s"] * ((this["s"] >= C_ZERO ? C_ONE : C_ZERO) + C_TWO * (places * this["n"] % this["d"]) > this["d"] ? C_ONE : C_ZERO), 708 places); 709 }, 710 711 /** 712 * Check if two rational numbers are divisible 713 * 714 * Ex: new Fraction(19.6).divisible(1.5); 715 */ 716 "divisible": function(a, b) { 717 718 parse(a, b); 719 return !(!(P["n"] * this["d"]) || ((this["n"] * P["d"]) % (P["n"] * this["d"]))); 720 }, 721 722 /** 723 * Returns a decimal representation of the fraction 724 * 725 * Ex: new Fraction("100.'91823'").valueOf() => 100.91823918239183 726 **/ 727 'valueOf': function() { 728 // Best we can do so far 729 return Number(this["s"] * this["n"]) / Number(this["d"]); 730 }, 731 732 /** 733 * Creates a string representation of a fraction with all digits 734 * 735 * Ex: new Fraction("100.'91823'").toString() => "100.(91823)" 736 **/ 737 'toString': function(dec) { 738 739 let N = this["n"]; 740 let D = this["d"]; 741 742 dec = dec || 15; // 15 = decimal places when no repitation 743 744 let cycLen = cycleLen(N, D); // Cycle length 745 let cycOff = cycleStart(N, D, cycLen); // Cycle start 746 747 let str = this['s'] < C_ZERO ? "-" : ""; 748 749 // Append integer part 750 str+= N / D; 751 752 N%= D; 753 N*= C_TEN; 754 755 if (N) 756 str+= "."; 757 758 if (cycLen) { 759 760 for (let i = cycOff; i--;) { 761 str+= N / D; 762 N%= D; 763 N*= C_TEN; 764 } 765 str+= "("; 766 for (let i = cycLen; i--;) { 767 str+= N / D; 768 N%= D; 769 N*= C_TEN; 770 } 771 str+= ")"; 772 } else { 773 for (let i = dec; N && i--;) { 774 str+= N / D; 775 N%= D; 776 N*= C_TEN; 777 } 778 } 779 return str; 780 }, 781 782 /** 783 * Returns a string-fraction representation of a Fraction object 784 * 785 * Ex: new Fraction("1.'3'").toFraction() => "4 1/3" 786 **/ 787 'toFraction': function(excludeWhole) { 788 789 let n = this["n"]; 790 let d = this["d"]; 791 let str = this['s'] < C_ZERO ? "-" : ""; 792 793 if (d === C_ONE) { 794 str+= n; 795 } else { 796 let whole = n / d; 797 if (excludeWhole && whole > C_ZERO) { 798 str+= whole; 799 str+= " "; 800 n%= d; 801 } 802 803 str+= n; 804 str+= '/'; 805 str+= d; 806 } 807 return str; 808 }, 809 810 /** 811 * Returns a latex representation of a Fraction object 812 * 813 * Ex: new Fraction("1.'3'").toLatex() => "\frac{4}{3}" 814 **/ 815 'toLatex': function(excludeWhole) { 816 817 let n = this["n"]; 818 let d = this["d"]; 819 let str = this['s'] < C_ZERO ? "-" : ""; 820 821 if (d === C_ONE) { 822 str+= n; 823 } else { 824 let whole = n / d; 825 if (excludeWhole && whole > C_ZERO) { 826 str+= whole; 827 n%= d; 828 } 829 830 str+= "\\frac{"; 831 str+= n; 832 str+= '}{'; 833 str+= d; 834 str+= '}'; 835 } 836 return str; 837 }, 838 839 /** 840 * Returns an array of continued fraction elements 841 * 842 * Ex: new Fraction("7/8").toContinued() => [0,1,7] 843 */ 844 'toContinued': function() { 845 846 let a = this['n']; 847 let b = this['d']; 848 let res = []; 849 850 do { 851 res.push(a / b); 852 let t = a % b; 853 a = b; 854 b = t; 855 } while (a !== C_ONE); 856 857 return res; 858 }, 859 860 "simplify": function(eps) { 861 862 eps = eps || 0.001; 863 864 const thisABS = this['abs'](); 865 const cont = thisABS['toContinued'](); 866 867 for (let i = 1; i < cont.length; i++) { 868 869 let s = newFraction(cont[i - 1], C_ONE); 870 for (let k = i - 2; k >= 0; k--) { 871 s = s['inverse']()['add'](cont[k]); 872 } 873 874 if (s['sub'](thisABS)['abs']().valueOf() < eps) { 875 return s['mul'](this['s']); 876 } 877 } 878 return this; 879 } 880 }; 881 882 if (typeof define === "function" && define["amd"]) { 883 define([], function() { 884 return Fraction; 885 }); 886 } else if (typeof exports === "object") { 887 Object.defineProperty(exports, "__esModule", { 'value': true }); 888 Fraction['default'] = Fraction; 889 Fraction['Fraction'] = Fraction; 890 module['exports'] = Fraction; 891 } else { 892 root['Fraction'] = Fraction; 893 } 894 895 })(this);