JAVASCRIPT 24
Bigfraction.js Guest on 20th April 2021 04:46:16 PM
  1. /**
  2.  * @license Fraction.js v4.0.12 09/09/2015
  3.  * http://www.xarg.org/2014/03/rational-numbers-in-javascript/
  4.  *
  5.  * Copyright (c) 2015, 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) { 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 = BigInt(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 createError(name) {
  66.  
  67.     function errorConstructor() {
  68.       const temp = Error.apply(this, arguments);
  69.       temp['name'] = this['name'] = name;
  70.       this['stack'] = temp['stack'];
  71.       this['message'] = temp['message'];
  72.     }
  73.  
  74.     /**
  75.      * Error constructor
  76.      *
  77.      * @constructor
  78.      */
  79.     function IntermediateInheritor() { }
  80.     IntermediateInheritor.prototype = Error.prototype;
  81.     errorConstructor.prototype = new IntermediateInheritor();
  82.  
  83.     return errorConstructor;
  84.   }
  85.  
  86.   const DivisionByZero = Fraction['DivisionByZero'] = createError('DivisionByZero');
  87.   const InvalidParameter = Fraction['InvalidParameter'] = createError('InvalidParameter');
  88.  
  89.   function assign(n, s) {
  90.  
  91.     try {
  92.       n = BigInt(n);
  93.     } catch (e) {
  94.       throw new InvalidParameter();
  95.     }
  96.  
  97.     return n * s;
  98.   }
  99.  
  100.   const parse = function(p1, p2) {
  101.  
  102.     let n = C_ZERO, d = C_ONE, s = C_ONE;
  103.  
  104.     if (p1 === undefined || p1 === null) {
  105.       /* void */
  106.     } else if (p2 !== undefined) {
  107.       n = BigInt(p1);
  108.       d = BigInt(p2);
  109.       s = n * d;
  110.     } else if (typeof p1 === "object") {
  111.       if ("d" in p1 && "n" in p1) {
  112.         n = BigInt(p1["n"]);
  113.         d = BigInt(p1["d"]);
  114.         if ("s" in p1)
  115.           n *= BigInt(p1["s"]);
  116.       } else if (0 in p1) {
  117.         n = BigInt(p1[0]);
  118.         if (1 in p1)
  119.           d = BigInt(p1[1]);
  120.       } else if (p1 instanceof BigInt) {
  121.         n = BigInt(p1);
  122.       } else {
  123.         throw new InvalidParameter();
  124.       }
  125.       s = n * d;
  126.     } else if (typeof p1 === "bigint") {
  127.       n = p1;
  128.       s = p1;
  129.       d = BigInt(1);
  130.     } else if (typeof p1 === "number") {
  131.  
  132.       if (isNaN(p1)) {
  133.         throw new InvalidParameter();
  134.       }
  135.  
  136.       if (p1 < 0) {
  137.         s = -C_ONE;
  138.         p1 = -p1;
  139.       }
  140.  
  141.       if (p1 % 1 === 0) {
  142.         n = BigInt(p1);
  143.       } else if (p1 > 0) { // check for != 0, scale would become NaN (log(0)), which converges really slow
  144.  
  145.         let z = 1;
  146.  
  147.         let A = 0, B = 1;
  148.         let C = 1, D = 1;
  149.  
  150.         let N = 10000000;
  151.  
  152.         if (p1 >= 1) {
  153.           z = 10 ** Math.floor(1 + Math.log10(p1));
  154.           p1 /= z;
  155.         }
  156.  
  157.         // Using Farey Sequences
  158.  
  159.         while (B <= N && D <= N) {
  160.           let M = (A + C) / (B + D);
  161.  
  162.           if (p1 === M) {
  163.             if (B + D <= N) {
  164.               n = A + C;
  165.               d = B + D;
  166.             } else if (D > B) {
  167.               n = C;
  168.               d = D;
  169.             } else {
  170.               n = A;
  171.               d = B;
  172.             }
  173.             break;
  174.  
  175.           } else {
  176.  
  177.             if (p1 > M) {
  178.               A += C;
  179.               B += D;
  180.             } else {
  181.               C += A;
  182.               D += B;
  183.             }
  184.  
  185.             if (B > N) {
  186.               n = C;
  187.               d = D;
  188.             } else {
  189.               n = A;
  190.               d = B;
  191.             }
  192.           }
  193.         }
  194.         n = BigInt(n) * BigInt(z);
  195.         d = BigInt(d);
  196.  
  197.       } else if (isNaN(p1)) {
  198.         d = n = NaN;
  199.       }
  200.  
  201.     } else if (typeof p1 === "string") {
  202.  
  203.       let ndx = 0;
  204.  
  205.       let v = C_ZERO, w = C_ZERO, x = C_ZERO, y = C_ONE, z = C_ONE;
  206.  
  207.       let match = p1.match(/\d+|./g);
  208.  
  209.       if (match === null)
  210.         throw new InvalidParameter()
  211.  
  212.       if (match[ndx] === '-') {// Check for minus sign at the beginning
  213.         s = -C_ONE;
  214.         ndx++;
  215.       } else if (match[ndx] === '+') {// Check for plus sign at the beginning
  216.         ndx++;
  217.       }
  218.  
  219.       if (match.length === ndx + 1) { // Check if it's just a simple number "1234"
  220.         w = assign(match[ndx++], s);
  221.       } else if (match[ndx + 1] === '.' || match[ndx] === '.') { // Check if it's a decimal number
  222.  
  223.         if (match[ndx] !== '.') { // Handle 0.5 and .5
  224.           v = assign(match[ndx++], s);
  225.         }
  226.         ndx++;
  227.  
  228.         // Check for decimal places
  229.         if (ndx + 1 === match.length || match[ndx + 1] === '(' && match[ndx + 3] === ')' || match[ndx + 1] === "'" && match[ndx + 3] === "'") {
  230.           w = assign(match[ndx], s);
  231.           y = C_TEN ** BigInt(match[ndx].length);
  232.           ndx++;
  233.         }
  234.  
  235.         // Check for repeating places
  236.         if (match[ndx] === '(' && match[ndx + 2] === ')' || match[ndx] === "'" && match[ndx + 2] === "'") {
  237.           x = assign(match[ndx + 1], s);
  238.           z = C_TEN ** BigInt(match[ndx + 1].length) - C_ONE;
  239.           ndx += 3;
  240.         }
  241.  
  242.       } else if (match[ndx + 1] === '/' || match[ndx + 1] === ':') { // Check for a simple fraction "123/456" or "123:456"
  243.         w = assign(match[ndx], s);
  244.         y = assign(match[ndx + 2], C_ONE);
  245.         ndx += 3;
  246.       } else if (match[ndx + 3] === '/' && match[ndx + 1] === ' ') { // Check for a complex fraction "123 1/2"
  247.         v = assign(match[ndx], s);
  248.         w = assign(match[ndx + 2], s);
  249.         y = assign(match[ndx + 4], C_ONE);
  250.         ndx += 5;
  251.       }
  252.  
  253.       if (match.length <= ndx) { // Check for more tokens on the stack
  254.         d = y * z;
  255.         s = /* void */
  256.         n = x + d * v + z * w;
  257.       } else {
  258.         throw new InvalidParameter();
  259.       }
  260.  
  261.     } else {
  262.       throw new InvalidParameter();
  263.     }
  264.  
  265.     if (d === C_ZERO) {
  266.       throw new DivisionByZero();
  267.     }
  268.  
  269.     P["s"] = s < C_ZERO ? -C_ONE : C_ONE;
  270.     P["n"] = n < C_ZERO ? -n : n;
  271.     P["d"] = d < C_ZERO ? -d : d;
  272.  
  273.   };
  274.  
  275.   function modpow(b, e, m) {
  276.  
  277.     let r = C_ONE;
  278.     for (; e > C_ZERO; b = (b * b) % m, e >>= C_ONE) {
  279.  
  280.       if (e & C_ONE) {
  281.         r = (r * b) % m;
  282.       }
  283.     }
  284.     return r;
  285.   }
  286.  
  287.   function cycleLen(n, d) {
  288.  
  289.     for (; d % C_TWO === C_ZERO;
  290.       d /= C_TWO) {
  291.     }
  292.  
  293.     for (; d % C_FIVE === C_ZERO;
  294.       d /= C_FIVE) {
  295.     }
  296.  
  297.     if (d === C_ONE) // Catch non-cyclic numbers
  298.       return C_ZERO;
  299.  
  300.     // If we would like to compute really large numbers quicker, we could make use of Fermat's little theorem:
  301.     // 10^(d-1) % d == 1
  302.     // However, we don't need such large numbers and MAX_CYCLE_LEN should be the capstone,
  303.     // as we want to translate the numbers to strings.
  304.  
  305.     let rem = C_TEN % d;
  306.     let t = C_ONE;
  307.  
  308.     for (; rem !== C_ONE; t++) {
  309.       rem = rem * C_TEN % d;
  310.  
  311.       if (t > MAX_CYCLE_LEN)
  312.         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`
  313.     }
  314.     return t;
  315.   }
  316.  
  317.   function cycleStart(n, d, len) {
  318.  
  319.     let rem1 = C_ONE;
  320.     let rem2 = modpow(C_TEN, len, d);
  321.  
  322.     for (let t = 0; t < 300; t++) { // s < ~log10(Number.MAX_VALUE)
  323.       // Solve 10^s == 10^(s+t) (mod d)
  324.  
  325.       if (rem1 === rem2)
  326.         return BigInt(t);
  327.  
  328.       rem1 = rem1 * C_TEN % d;
  329.       rem2 = rem2 * C_TEN % d;
  330.     }
  331.     return 0;
  332.   }
  333.  
  334.   function gcd(a, b) {
  335.  
  336.     if (!a)
  337.       return b;
  338.     if (!b)
  339.       return a;
  340.  
  341.     while (1) {
  342.       a %= b;
  343.       if (!a)
  344.         return b;
  345.       b %= a;
  346.       if (!b)
  347.         return a;
  348.     }
  349.   }
  350.  
  351.   /**
  352.    * Module constructor
  353.    *
  354.    * @constructor
  355.    * @param {number|Fraction=} a
  356.    * @param {number=} b
  357.    */
  358.   function Fraction(a, b) {
  359.  
  360.     if (!(this instanceof Fraction)) {
  361.       return new Fraction(a, b);
  362.     }
  363.  
  364.     parse(a, b);
  365.  
  366.     a = gcd(P["d"], P["n"]); // Abuse a
  367.  
  368.     this["s"] = P["s"];
  369.     this["n"] = P["n"] / a | C_ZERO;
  370.     this["d"] = P["d"] / a | C_ZERO;
  371.   }
  372.  
  373.   Fraction.prototype = {
  374.  
  375.     "s": C_ONE,
  376.     "n": C_ZERO,
  377.     "d": C_ONE,
  378.  
  379.     /**
  380.      * Calculates the absolute value
  381.      *
  382.      * Ex: new Fraction(-4).abs() => 4
  383.      **/
  384.     "abs": function() {
  385.  
  386.       return new Fraction(this["n"], this["d"]);
  387.     },
  388.  
  389.     /**
  390.      * Inverts the sign of the current fraction
  391.      *
  392.      * Ex: new Fraction(-4).neg() => 4
  393.      **/
  394.     "neg": function() {
  395.  
  396.       return new Fraction(-this["s"] * this["n"], this["d"]);
  397.     },
  398.  
  399.     /**
  400.      * Adds two rational numbers
  401.      *
  402.      * Ex: new Fraction({n: 2, d: 3}).add("14.9") => 467 / 30
  403.      **/
  404.     "add": function(a, b) {
  405.  
  406.       parse(a, b);
  407.       return new Fraction(
  408.         this["s"] * this["n"] * P["d"] + P["s"] * this["d"] * P["n"],
  409.         this["d"] * P["d"]
  410.       );
  411.     },
  412.  
  413.     /**
  414.      * Subtracts two rational numbers
  415.      *
  416.      * Ex: new Fraction({n: 2, d: 3}).add("14.9") => -427 / 30
  417.      **/
  418.     "sub": function(a, b) {
  419.  
  420.       parse(a, b);
  421.       return new Fraction(
  422.         this["s"] * this["n"] * P["d"] - P["s"] * this["d"] * P["n"],
  423.         this["d"] * P["d"]
  424.       );
  425.     },
  426.  
  427.     /**
  428.      * Multiplies two rational numbers
  429.      *
  430.      * Ex: new Fraction("-17.(345)").mul(3) => 5776 / 111
  431.      **/
  432.     "mul": function(a, b) {
  433.  
  434.       parse(a, b);
  435.       return new Fraction(
  436.         this["s"] * P["s"] * this["n"] * P["n"],
  437.         this["d"] * P["d"]
  438.       );
  439.     },
  440.  
  441.     /**
  442.      * Divides two rational numbers
  443.      *
  444.      * Ex: new Fraction("-17.(345)").inverse().div(3)
  445.      **/
  446.     "div": function(a, b) {
  447.  
  448.       parse(a, b);
  449.       return new Fraction(
  450.         this["s"] * P["s"] * this["n"] * P["d"],
  451.         this["d"] * P["n"]
  452.       );
  453.     },
  454.  
  455.     /**
  456.      * Clones the actual object
  457.      *
  458.      * Ex: new Fraction("-17.(345)").clone()
  459.      **/
  460.     "clone": function() {
  461.       return new Fraction(this);
  462.     },
  463.  
  464.     /**
  465.      * Calculates the modulo of two rational numbers - a more precise fmod
  466.      *
  467.      * Ex: new Fraction('4.(3)').mod([7, 8]) => (13/3) % (7/8) = (5/6)
  468.      **/
  469.     "mod": function(a, b) {
  470.  
  471.       if (a === undefined) {
  472.         return new Fraction(this["s"] * this["n"] % this["d"], 1);
  473.       }
  474.  
  475.       parse(a, b);
  476.       if (0 === P["n"] && 0 === this["d"]) {
  477.         Fraction(0, 0); // Throw DivisionByZero
  478.       }
  479.  
  480.       /*
  481.        * First silly attempt, kinda slow
  482.        *
  483.        return that["sub"]({
  484.        "n": num["n"] * Math.floor((this.n / this.d) / (num.n / num.d)),
  485.        "d": num["d"],
  486.        "s": this["s"]
  487.        });*/
  488.  
  489.       /*
  490.        * New attempt: a1 / b1 = a2 / b2 * q + r
  491.        * => b2 * a1 = a2 * b1 * q + b1 * b2 * r
  492.        * => (b2 * a1 % a2 * b1) / (b1 * b2)
  493.        */
  494.       return new Fraction(
  495.         this["s"] * (P["d"] * this["n"]) % (P["n"] * this["d"]),
  496.         P["d"] * this["d"]
  497.       );
  498.     },
  499.  
  500.     /**
  501.      * Calculates the fractional gcd of two rational numbers
  502.      *
  503.      * Ex: new Fraction(5,8).gcd(3,7) => 1/56
  504.      */
  505.     "gcd": function(a, b) {
  506.  
  507.       parse(a, b);
  508.  
  509.       // gcd(a / b, c / d) = gcd(a, c) / lcm(b, d)
  510.  
  511.       return new Fraction(gcd(P["n"], this["n"]) * gcd(P["d"], this["d"]), P["d"] * this["d"]);
  512.     },
  513.  
  514.     /**
  515.      * Calculates the fractional lcm of two rational numbers
  516.      *
  517.      * Ex: new Fraction(5,8).lcm(3,7) => 15
  518.      */
  519.     "lcm": function(a, b) {
  520.  
  521.       parse(a, b);
  522.  
  523.       // lcm(a / b, c / d) = lcm(a, c) / gcd(b, d)
  524.  
  525.       if (P["n"] === C_ZERO && this["n"] === C_ZERO) {
  526.         return new Fraction;
  527.       }
  528.       return new Fraction(P["n"] * this["n"], gcd(P["n"], this["n"]) * gcd(P["d"], this["d"]));
  529.     },
  530.  
  531.     /**
  532.      * Gets the inverse of the fraction, means numerator and denominator are exchanged
  533.      *
  534.      * Ex: new Fraction([-3, 4]).inverse() => -4 / 3
  535.      **/
  536.     "inverse": function() {
  537.  
  538.       return new Fraction(this["s"] * this["d"], this["n"]);
  539.     },
  540.  
  541.     /**
  542.      * Calculates the fraction to some integer exponent
  543.      *
  544.      * Ex: new Fraction(-1,2).pow(-3) => -8
  545.      */
  546.     "pow": function(m) {
  547.  
  548.       if (m < 0) {
  549.         return new Fraction((this['s'] * this["d"]) ** BigInt(-m), this["n"] ** BigInt(-m));
  550.       } else {
  551.         return new Fraction((this['s'] * this["n"]) ** BigInt(+m), this["d"] ** BigInt(+m));
  552.       }
  553.     },
  554.  
  555.     /**
  556.      * Check if two rational numbers are the same
  557.      *
  558.      * Ex: new Fraction(19.6).equals([98, 5]);
  559.      **/
  560.     "equals": function(a, b) {
  561.  
  562.       parse(a, b);
  563.       return this["s"] * this["n"] * P["d"] === P["s"] * P["n"] * this["d"]; // Same as compare() === 0
  564.     },
  565.  
  566.     /**
  567.      * Check if two rational numbers are the same
  568.      *
  569.      * Ex: new Fraction(19.6).equals([98, 5]);
  570.      **/
  571.     "compare": function(a, b) {
  572.  
  573.       parse(a, b);
  574.       let t = (this["s"] * this["n"] * P["d"] - P["s"] * P["n"] * this["d"]);
  575.  
  576.       return (C_ZERO < t) - (t < C_ZERO);
  577.     },
  578.  
  579.     /**
  580.      * Calculates the ceil of a rational number
  581.      *
  582.      * Ex: new Fraction('4.(3)').ceil() => (5 / 1)
  583.      **/
  584.     "ceil": function(places) {
  585.  
  586.       places = 10 ** Number(places || 0);
  587.  
  588.       return new Fraction(Math.ceil(places * Number(this["s"] * this["n"]) / Number(this["d"])), places);
  589.     },
  590.  
  591.     /**
  592.      * Calculates the floor of a rational number
  593.      *
  594.      * Ex: new Fraction('4.(3)').floor() => (4 / 1)
  595.      **/
  596.     "floor": function(places) {
  597.  
  598.       places = 10 ** Number(places || 0);
  599.  
  600.       return new Fraction(Math.floor(places * Number(this["s"] * this["n"]) / Number(this["d"])), places);
  601.     },
  602.  
  603.     /**
  604.      * Rounds a rational numbers
  605.      *
  606.      * Ex: new Fraction('4.(3)').round() => (4 / 1)
  607.      **/
  608.     "round": function(places) {
  609.  
  610.       places = 10 ** Number(places || 0);
  611.  
  612.       return new Fraction(Math.round(places * Number(this["s"] * this["n"]) / Number(this["d"])), places);
  613.     },
  614.  
  615.     /**
  616.      * Check if two rational numbers are divisible
  617.      *
  618.      * Ex: new Fraction(19.6).divisible(1.5);
  619.      */
  620.     "divisible": function(a, b) {
  621.  
  622.       parse(a, b);
  623.       return !(!(P["n"] * this["d"]) || ((this["n"] * P["d"]) % (P["n"] * this["d"])));
  624.     },
  625.  
  626.     /**
  627.      * Returns a decimal representation of the fraction
  628.      *
  629.      * Ex: new Fraction("100.'91823'").valueOf() => 100.91823918239183
  630.      **/
  631.     'valueOf': function() {
  632.       // Best we can do so far
  633.       return Number(this["s"] * this["n"]) / Number(this["d"]);
  634.     },
  635.  
  636.     /**
  637.      * Creates a string representation of a fraction with all digits
  638.      *
  639.      * Ex: new Fraction("100.'91823'").toString() => "100.(91823)"
  640.      **/
  641.     'toString': function(dec) {
  642.  
  643.       let g;
  644.       let N = this["n"];
  645.       let D = this["d"];
  646.  
  647.       dec = dec || 15; // 15 = decimal places when no repitation
  648.  
  649.       let cycLen = cycleLen(N, D); // Cycle length
  650.       let cycOff = cycleStart(N, D, cycLen); // Cycle start
  651.  
  652.       let str = this['s'] < C_ZERO ? "-" : "";
  653.  
  654.       // Append integer part
  655.       str += N / D | C_ZERO;
  656.  
  657.       N %= D;
  658.       N *= C_TEN;
  659.  
  660.       if (N)
  661.         str += ".";
  662.  
  663.       if (cycLen) {
  664.  
  665.         for (let i = cycOff; i--;) {
  666.           str += N / D | C_ZERO;
  667.           N %= D;
  668.           N *= C_TEN;
  669.         }
  670.         str += "(";
  671.         for (let i = cycLen; i--;) {
  672.           str += N / D | C_ZERO;
  673.           N %= D;
  674.           N *= C_TEN;
  675.         }
  676.         str += ")";
  677.       } else {
  678.         for (let i = dec; N && i--;) {
  679.           str += N / D | C_ZERO;
  680.           N %= D;
  681.           N *= C_TEN;
  682.         }
  683.       }
  684.       return str;
  685.     },
  686.  
  687.     /**
  688.      * Returns a string-fraction representation of a Fraction object
  689.      *
  690.      * Ex: new Fraction("1.'3'").toFraction() => "4 1/3"
  691.      **/
  692.     'toFraction': function(excludeWhole) {
  693.  
  694.       let n = this["n"];
  695.       let d = this["d"];
  696.       let str = this['s'] < C_ZERO ? "-" : "";
  697.  
  698.       if (d === C_ONE) {
  699.         str += n;
  700.       } else {
  701.         let whole = n / d | C_ZERO;
  702.         if (excludeWhole && whole > C_ZERO) {
  703.           str += whole;
  704.           str += " ";
  705.           n %= d;
  706.         }
  707.  
  708.         str += n;
  709.         str += '/';
  710.         str += d;
  711.       }
  712.       return str;
  713.     },
  714.  
  715.     /**
  716.      * Returns a latex representation of a Fraction object
  717.      *
  718.      * Ex: new Fraction("1.'3'").toLatex() => "\frac{4}{3}"
  719.      **/
  720.     'toLatex': function(excludeWhole) {
  721.  
  722.       let n = this["n"];
  723.       let d = this["d"];
  724.       let str = this['s'] < C_ZERO ? "-" : "";
  725.  
  726.       if (d === C_ONE) {
  727.         str += n;
  728.       } else {
  729.         let whole = n / d | C_ZERO;
  730.         if (excludeWhole && whole > C_ZERO) {
  731.           str += whole;
  732.           n %= d;
  733.         }
  734.  
  735.         str += "\\frac{";
  736.         str += n;
  737.         str += '}{';
  738.         str += d;
  739.         str += '}';
  740.       }
  741.       return str;
  742.     },
  743.  
  744.     /**
  745.      * Returns an array of continued fraction elements
  746.      *
  747.      * Ex: new Fraction("7/8").toContinued() => [0,1,7]
  748.      */
  749.     'toContinued': function() {
  750.  
  751.       let a = this['n'];
  752.       let b = this['d'];
  753.       let res = [];
  754.  
  755.       do {
  756.         res.push(a / b | C_ZERO);
  757.         let t = a % b;
  758.         a = b;
  759.         b = t;
  760.       } while (a !== C_ONE);
  761.  
  762.       return res;
  763.     },
  764.  
  765.     "simplify": function(eps) {
  766.  
  767.       // First naive implementation, needs improvement
  768.  
  769.       let cont = this['abs']()['toContinued']();
  770.  
  771.       eps = eps || 0.001;
  772.  
  773.       function rec(a) {
  774.         if (a.length === 1)
  775.           return new Fraction(a[0]);
  776.         return rec(a.slice(1))['inverse']()['add'](a[0]);
  777.       }
  778.  
  779.       for (let i = 0; i < cont.length; i++) {
  780.         let tmp = rec(cont.slice(0, i + 1));
  781.         if (tmp['sub'](this['abs']())['abs']().valueOf() < eps) {
  782.           return tmp['mul'](this['s']);
  783.         }
  784.       }
  785.       return this;
  786.     }
  787.   };
  788.  
  789.   if (typeof define === "function" && define["amd"]) {
  790.     define([], function() {
  791.       return Fraction;
  792.     });
  793.   } else if (typeof exports === "object") {
  794.     Object.defineProperty(exports, "__esModule", { 'value': true });
  795.     Fraction['default'] = Fraction;
  796.     Fraction['Fraction'] = Fraction;
  797.     module['exports'] = Fraction;
  798.   } else {
  799.     root['Fraction'] = Fraction;
  800.   }
  801.  
  802. })(this);

Paste-bin is for source code and general debugging text.

Login or Register to edit, delete and keep track of your pastes and more.

Raw Paste

Login or Register to edit or fork this paste. It's free.