fraction.cjs 20 KB

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