fraction.cjs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904
  1. /**
  2. * @license Fraction.js v4.3.7 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. * Rounds a rational number to a multiple of another rational number
  482. *
  483. * Ex: new Fraction('0.9').roundTo("1/8") => 7 / 8
  484. **/
  485. "roundTo": function(a, b) {
  486. /*
  487. k * x/y ≤ a/b < (k+1) * x/y
  488. ⇔ k ≤ a/b / (x/y) < (k+1)
  489. ⇔ k = floor(a/b * y/x)
  490. */
  491. parse(a, b);
  492. return newFraction(this['s'] * Math.round(this['n'] * P['d'] / (this['d'] * P['n'])) * P['n'], P['d']);
  493. },
  494. /**
  495. * Gets the inverse of the fraction, means numerator and denominator are exchanged
  496. *
  497. * Ex: new Fraction([-3, 4]).inverse() => -4 / 3
  498. **/
  499. "inverse": function() {
  500. return newFraction(this["s"] * this["d"], this["n"]);
  501. },
  502. /**
  503. * Calculates the fraction to some rational exponent, if possible
  504. *
  505. * Ex: new Fraction(-1,2).pow(-3) => -8
  506. */
  507. "pow": function(a, b) {
  508. parse(a, b);
  509. // Trivial case when exp is an integer
  510. if (P['d'] === 1) {
  511. if (P['s'] < 0) {
  512. return newFraction(Math.pow(this['s'] * this["d"], P['n']), Math.pow(this["n"], P['n']));
  513. } else {
  514. return newFraction(Math.pow(this['s'] * this["n"], P['n']), Math.pow(this["d"], P['n']));
  515. }
  516. }
  517. // Negative roots become complex
  518. // (-a/b)^(c/d) = x
  519. // <=> (-1)^(c/d) * (a/b)^(c/d) = x
  520. // <=> (cos(pi) + i*sin(pi))^(c/d) * (a/b)^(c/d) = x # rotate 1 by 180°
  521. // <=> (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 )
  522. // 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.
  523. if (this['s'] < 0) return null;
  524. // Now prime factor n and d
  525. var N = factorize(this['n']);
  526. var D = factorize(this['d']);
  527. // Exponentiate and take root for n and d individually
  528. var n = 1;
  529. var d = 1;
  530. for (var k in N) {
  531. if (k === '1') continue;
  532. if (k === '0') {
  533. n = 0;
  534. break;
  535. }
  536. N[k]*= P['n'];
  537. if (N[k] % P['d'] === 0) {
  538. N[k]/= P['d'];
  539. } else return null;
  540. n*= Math.pow(k, N[k]);
  541. }
  542. for (var k in D) {
  543. if (k === '1') continue;
  544. D[k]*= P['n'];
  545. if (D[k] % P['d'] === 0) {
  546. D[k]/= P['d'];
  547. } else return null;
  548. d*= Math.pow(k, D[k]);
  549. }
  550. if (P['s'] < 0) {
  551. return newFraction(d, n);
  552. }
  553. return newFraction(n, d);
  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. parse(a, b);
  562. return this["s"] * this["n"] * P["d"] === P["s"] * P["n"] * this["d"]; // Same as compare() === 0
  563. },
  564. /**
  565. * Check if two rational numbers are the same
  566. *
  567. * Ex: new Fraction(19.6).equals([98, 5]);
  568. **/
  569. "compare": function(a, b) {
  570. parse(a, b);
  571. var t = (this["s"] * this["n"] * P["d"] - P["s"] * P["n"] * this["d"]);
  572. return (0 < t) - (t < 0);
  573. },
  574. "simplify": function(eps) {
  575. if (isNaN(this['n']) || isNaN(this['d'])) {
  576. return this;
  577. }
  578. eps = eps || 0.001;
  579. var thisABS = this['abs']();
  580. var cont = thisABS['toContinued']();
  581. for (var i = 1; i < cont.length; i++) {
  582. var s = newFraction(cont[i - 1], 1);
  583. for (var k = i - 2; k >= 0; k--) {
  584. s = s['inverse']()['add'](cont[k]);
  585. }
  586. if (Math.abs(s['sub'](thisABS).valueOf()) < eps) {
  587. return s['mul'](this['s']);
  588. }
  589. }
  590. return this;
  591. },
  592. /**
  593. * Check if two rational numbers are divisible
  594. *
  595. * Ex: new Fraction(19.6).divisible(1.5);
  596. */
  597. "divisible": function(a, b) {
  598. parse(a, b);
  599. return !(!(P["n"] * this["d"]) || ((this["n"] * P["d"]) % (P["n"] * this["d"])));
  600. },
  601. /**
  602. * Returns a decimal representation of the fraction
  603. *
  604. * Ex: new Fraction("100.'91823'").valueOf() => 100.91823918239183
  605. **/
  606. 'valueOf': function() {
  607. return this["s"] * this["n"] / this["d"];
  608. },
  609. /**
  610. * Returns a string-fraction representation of a Fraction object
  611. *
  612. * Ex: new Fraction("1.'3'").toFraction(true) => "4 1/3"
  613. **/
  614. 'toFraction': function(excludeWhole) {
  615. var whole, str = "";
  616. var n = this["n"];
  617. var d = this["d"];
  618. if (this["s"] < 0) {
  619. str+= '-';
  620. }
  621. if (d === 1) {
  622. str+= n;
  623. } else {
  624. if (excludeWhole && (whole = Math.floor(n / d)) > 0) {
  625. str+= whole;
  626. str+= " ";
  627. n%= d;
  628. }
  629. str+= n;
  630. str+= '/';
  631. str+= d;
  632. }
  633. return str;
  634. },
  635. /**
  636. * Returns a latex representation of a Fraction object
  637. *
  638. * Ex: new Fraction("1.'3'").toLatex() => "\frac{4}{3}"
  639. **/
  640. 'toLatex': function(excludeWhole) {
  641. var whole, str = "";
  642. var n = this["n"];
  643. var d = this["d"];
  644. if (this["s"] < 0) {
  645. str+= '-';
  646. }
  647. if (d === 1) {
  648. str+= n;
  649. } else {
  650. if (excludeWhole && (whole = Math.floor(n / d)) > 0) {
  651. str+= whole;
  652. n%= d;
  653. }
  654. str+= "\\frac{";
  655. str+= n;
  656. str+= '}{';
  657. str+= d;
  658. str+= '}';
  659. }
  660. return str;
  661. },
  662. /**
  663. * Returns an array of continued fraction elements
  664. *
  665. * Ex: new Fraction("7/8").toContinued() => [0,1,7]
  666. */
  667. 'toContinued': function() {
  668. var t;
  669. var a = this['n'];
  670. var b = this['d'];
  671. var res = [];
  672. if (isNaN(a) || isNaN(b)) {
  673. return res;
  674. }
  675. do {
  676. res.push(Math.floor(a / b));
  677. t = a % b;
  678. a = b;
  679. b = t;
  680. } while (a !== 1);
  681. return res;
  682. },
  683. /**
  684. * Creates a string representation of a fraction with all digits
  685. *
  686. * Ex: new Fraction("100.'91823'").toString() => "100.(91823)"
  687. **/
  688. 'toString': function(dec) {
  689. var N = this["n"];
  690. var D = this["d"];
  691. if (isNaN(N) || isNaN(D)) {
  692. return "NaN";
  693. }
  694. dec = dec || 15; // 15 = decimal places when no repetation
  695. var cycLen = cycleLen(N, D); // Cycle length
  696. var cycOff = cycleStart(N, D, cycLen); // Cycle start
  697. var str = this['s'] < 0 ? "-" : "";
  698. str+= N / D | 0;
  699. N%= D;
  700. N*= 10;
  701. if (N)
  702. str+= ".";
  703. if (cycLen) {
  704. for (var i = cycOff; i--;) {
  705. str+= N / D | 0;
  706. N%= D;
  707. N*= 10;
  708. }
  709. str+= "(";
  710. for (var i = cycLen; i--;) {
  711. str+= N / D | 0;
  712. N%= D;
  713. N*= 10;
  714. }
  715. str+= ")";
  716. } else {
  717. for (var i = dec; N && i--;) {
  718. str+= N / D | 0;
  719. N%= D;
  720. N*= 10;
  721. }
  722. }
  723. return str;
  724. }
  725. };
  726. if (typeof exports === "object") {
  727. Object.defineProperty(exports, "__esModule", { 'value': true });
  728. exports['default'] = Fraction;
  729. module['exports'] = Fraction;
  730. } else {
  731. root['Fraction'] = Fraction;
  732. }
  733. })(this);