fraction.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // FIXME: Check the operators' names
  2. // FIXME: This class should probably be immutable?
  3. "use strict";
  4. var Fraction = (function () {
  5. function Fraction(numerator, denominator, simplify) {
  6. if (numerator === void 0) { numerator = 0; }
  7. if (denominator === void 0) { denominator = 1; }
  8. if (simplify === void 0) { simplify = true; }
  9. this.numerator = 0;
  10. this.denominator = 1;
  11. this.numerator = numerator;
  12. this.denominator = denominator;
  13. if (simplify) {
  14. this.simplify();
  15. }
  16. this.setRealValue();
  17. }
  18. Fraction.max = function (f1, f2) {
  19. if (f1.RealValue > f2.RealValue) {
  20. return f1;
  21. }
  22. else {
  23. return f2;
  24. }
  25. };
  26. Fraction.Equal = function (f1, f2) {
  27. // FIXME
  28. return f1.Denominator === f2.Denominator && f1.Numerator === f2.Numerator;
  29. };
  30. Fraction.createFromFraction = function (fraction) {
  31. return new Fraction(fraction.numerator, fraction.denominator);
  32. };
  33. Fraction.plus = function (f1, f2) {
  34. var sum = f1.clone();
  35. sum.Add(f2);
  36. return sum;
  37. };
  38. Fraction.minus = function (f1, f2) {
  39. var sum = f1.clone();
  40. sum.Sub(f2);
  41. return sum;
  42. };
  43. Fraction.greatestCommonDenominator = function (a, b) {
  44. if (a === 0) {
  45. return b;
  46. }
  47. if (b === 1) {
  48. return 1;
  49. }
  50. while (b !== 0) {
  51. if (a > b) {
  52. a -= b;
  53. }
  54. else {
  55. b -= a;
  56. }
  57. }
  58. return a;
  59. };
  60. Fraction.prototype.toString = function () {
  61. return this.numerator + "/" + this.denominator;
  62. };
  63. Fraction.prototype.clone = function () {
  64. return new Fraction(this.numerator, this.denominator, false);
  65. };
  66. Object.defineProperty(Fraction.prototype, "Numerator", {
  67. get: function () {
  68. return this.numerator;
  69. },
  70. set: function (value) {
  71. if (this.numerator !== value) {
  72. this.numerator = value;
  73. this.simplify();
  74. this.setRealValue();
  75. }
  76. },
  77. enumerable: true,
  78. configurable: true
  79. });
  80. Object.defineProperty(Fraction.prototype, "Denominator", {
  81. get: function () {
  82. return this.denominator;
  83. },
  84. set: function (value) {
  85. if (this.denominator !== value) {
  86. this.denominator = value;
  87. if (this.numerator !== 0) {
  88. this.simplify();
  89. }
  90. this.setRealValue();
  91. }
  92. },
  93. enumerable: true,
  94. configurable: true
  95. });
  96. Object.defineProperty(Fraction.prototype, "RealValue", {
  97. get: function () {
  98. return this.realValue;
  99. },
  100. enumerable: true,
  101. configurable: true
  102. });
  103. Fraction.prototype.multiplyWithFactor = function (factor) {
  104. this.numerator *= factor;
  105. this.denominator *= factor;
  106. };
  107. Fraction.prototype.multiplyDenominatorWithFactor = function (factor) {
  108. this.denominator *= factor;
  109. this.setRealValue();
  110. };
  111. Fraction.prototype.Add = function (fraction) {
  112. this.numerator = this.numerator * fraction.denominator + fraction.numerator * this.denominator;
  113. this.denominator = this.denominator * fraction.denominator;
  114. this.simplify();
  115. this.setRealValue();
  116. };
  117. Fraction.prototype.Sub = function (fraction) {
  118. this.numerator = this.numerator * fraction.denominator - fraction.numerator * this.denominator;
  119. this.denominator = this.denominator * fraction.denominator;
  120. this.simplify();
  121. this.setRealValue();
  122. };
  123. Fraction.prototype.Quantize = function (maxAllowedDenominator) {
  124. if (this.denominator <= maxAllowedDenominator) {
  125. return this;
  126. }
  127. var upTestFraction = new Fraction(this.numerator + 1, this.denominator);
  128. while (upTestFraction.Denominator > maxAllowedDenominator) {
  129. upTestFraction.Numerator++;
  130. }
  131. if (this.numerator > this.denominator) {
  132. var downTestFraction = new Fraction(this.numerator - 1, this.denominator);
  133. while (downTestFraction.Denominator > maxAllowedDenominator) {
  134. downTestFraction.Numerator--;
  135. }
  136. if (downTestFraction.Denominator < upTestFraction.Denominator) {
  137. return downTestFraction;
  138. }
  139. }
  140. return upTestFraction;
  141. };
  142. Fraction.prototype.Equals = function (obj) {
  143. return this.RealValue === obj.RealValue;
  144. };
  145. Fraction.prototype.CompareTo = function (obj) {
  146. var diff = this.numerator * obj.Denominator - this.denominator * obj.Numerator;
  147. // Return the sign of diff
  148. return diff ? diff < 0 ? -1 : 1 : 0;
  149. };
  150. Fraction.prototype.lt = function (frac) {
  151. return (this.numerator * frac.Denominator - this.denominator * frac.Numerator) < 0;
  152. };
  153. Fraction.prototype.lte = function (frac) {
  154. return (this.numerator * frac.Denominator - this.denominator * frac.Numerator) <= 0;
  155. };
  156. //public Equals(f: Fraction): boolean {
  157. // if (ReferenceEquals(this, f))
  158. // return true;
  159. // if (ReferenceEquals(f, undefined))
  160. // return false;
  161. // return <number>this.numerator * f.denominator === <number>f.numerator * this.denominator;
  162. //}
  163. Fraction.prototype.GetInversion = function () {
  164. return new Fraction(this.denominator, this.numerator);
  165. };
  166. Fraction.prototype.setRealValue = function () {
  167. this.realValue = this.numerator / this.denominator;
  168. };
  169. Fraction.prototype.simplify = function () {
  170. if (this.numerator === 0) {
  171. this.denominator = 1;
  172. return;
  173. }
  174. var i = Fraction.greatestCommonDenominator(Math.abs(this.numerator), Math.abs(this.denominator));
  175. this.numerator /= i;
  176. this.denominator /= i;
  177. if (this.denominator > Fraction.maximumAllowedNumber) {
  178. var factor = this.denominator / Fraction.maximumAllowedNumber;
  179. this.numerator = Math.round(this.numerator / factor);
  180. this.denominator = Math.round(this.denominator / factor);
  181. }
  182. if (this.numerator > Fraction.maximumAllowedNumber) {
  183. var factor = this.numerator / Fraction.maximumAllowedNumber;
  184. this.numerator = Math.round(this.numerator / factor);
  185. this.denominator = Math.round(this.denominator / factor);
  186. }
  187. };
  188. Fraction.maximumAllowedNumber = 46340;
  189. return Fraction;
  190. }());
  191. exports.Fraction = Fraction;