fraction.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. // TODO: implement operators!
  2. export class Fraction /*implements IComparable, IComparer<Fraction> */{
  3. constructor(numerator: number = 0, denominator: number = 1, simplify: boolean = true) {
  4. this.numerator = numerator;
  5. this.denominator = denominator;
  6. if (simplify) { this.simplify(); }
  7. this.setRealValue();
  8. }
  9. private static maximumAllowedNumber: number = 46340;
  10. private numerator: number = 0;
  11. private denominator: number = 1;
  12. private realValue: number;
  13. public static Equal(f1: Fraction, f2: Fraction): boolean {
  14. // FIXME
  15. return f1.Denominator === f2.Denominator && f1.Numerator === f2.Numerator;
  16. }
  17. public static CreateFractionFromFraction(fraction: Fraction): Fraction {
  18. return new Fraction(fraction.numerator, fraction.denominator);
  19. }
  20. public static plus (f1: Fraction, f2: Fraction): Fraction {
  21. let sum: Fraction = Fraction.CreateFractionFromFraction(f1);
  22. sum.Add(f2);
  23. return sum;
  24. }
  25. public static minus (f1: Fraction , f2: Fraction): Fraction {
  26. let sum: Fraction = Fraction.CreateFractionFromFraction(f1);
  27. sum.Sub(f2);
  28. return sum;
  29. }
  30. private static greatestCommonDenominator(a: number, b: number): number {
  31. if (a === 0) {
  32. return b;
  33. }
  34. if (b === 1) {
  35. return 1;
  36. }
  37. while (b !== 0) {
  38. if (a > b) {
  39. a -= b;
  40. } else {
  41. b -= a;
  42. }
  43. }
  44. return a;
  45. }
  46. public clone(): Fraction {
  47. return new Fraction(this.numerator, this.denominator, false);
  48. }
  49. public get Numerator(): number {
  50. return this.numerator;
  51. }
  52. public set Numerator(value: number) {
  53. if (this.numerator !== value) {
  54. this.numerator = value;
  55. this.simplify();
  56. this.setRealValue();
  57. }
  58. }
  59. public get Denominator(): number {
  60. return this.denominator;
  61. }
  62. public set Denominator(value: number) {
  63. if (this.denominator !== value) {
  64. this.denominator = value;
  65. if (this.numerator !== 0) {
  66. this.simplify();
  67. }
  68. this.setRealValue();
  69. }
  70. }
  71. public get RealValue(): number {
  72. return this.realValue;
  73. }
  74. public multiplyWithFactor(factor: number): void {
  75. this.numerator *= factor;
  76. this.denominator *= factor;
  77. }
  78. public multiplyDenominatorWithFactor(factor: number): void {
  79. this.denominator *= factor;
  80. this.setRealValue();
  81. }
  82. public Add(fraction: Fraction): void {
  83. this.numerator = this.numerator * fraction.denominator + fraction.numerator * this.denominator;
  84. this.denominator = this.denominator * fraction.denominator;
  85. this.simplify();
  86. this.setRealValue();
  87. }
  88. public Sub(fraction: Fraction): void {
  89. this.numerator = this.numerator * fraction.denominator - fraction.numerator * this.denominator;
  90. this.denominator = this.denominator * fraction.denominator;
  91. this.simplify();
  92. this.setRealValue();
  93. }
  94. public Quantize(maxAllowedDenominator: number): Fraction {
  95. if (this.denominator <= maxAllowedDenominator) {
  96. return this;
  97. }
  98. let upTestFraction: Fraction = new Fraction(this.numerator + 1, this.denominator);
  99. while (upTestFraction.Denominator > maxAllowedDenominator) {
  100. upTestFraction.Numerator++;
  101. }
  102. if (this.numerator > this.denominator) {
  103. let downTestFraction: Fraction = new Fraction(this.numerator - 1, this.denominator);
  104. while (downTestFraction.Denominator > maxAllowedDenominator) {
  105. downTestFraction.Numerator--;
  106. }
  107. if (downTestFraction.Denominator < upTestFraction.Denominator) {
  108. return downTestFraction;
  109. }
  110. }
  111. return upTestFraction;
  112. }
  113. //public Equals(obj: Object): boolean {
  114. // if (ReferenceEquals(obj, null)) {
  115. // return false;
  116. // }
  117. // return this.Equals(__as__<Fraction>(obj, Fraction));
  118. //}
  119. //public Equals(f: Fraction): boolean {
  120. // if (ReferenceEquals(this, f))
  121. // return true;
  122. // if (ReferenceEquals(f, null))
  123. // return false;
  124. // return <number>this.numerator * f.denominator === <number>f.numerator * this.denominator;
  125. //}
  126. public GetInversion(): Fraction {
  127. return new Fraction(this.Denominator, this.Numerator);
  128. }
  129. private setRealValue(): void {
  130. this.realValue = this.numerator / this.denominator;
  131. }
  132. private simplify(): void {
  133. if (this.numerator === 0) {
  134. this.denominator = 1;
  135. return;
  136. }
  137. let i: number = Fraction.greatestCommonDenominator(Math.abs(this.numerator), Math.abs(this.denominator));
  138. this.numerator /= i;
  139. this.denominator /= i;
  140. if (this.denominator > Fraction.maximumAllowedNumber) {
  141. let factor: number = this.denominator / Fraction.maximumAllowedNumber;
  142. this.numerator = Math.round(this.numerator / factor);
  143. this.denominator = Math.round(this.denominator / factor);
  144. }
  145. if (this.numerator > Fraction.maximumAllowedNumber) {
  146. let factor: number = this.numerator / Fraction.maximumAllowedNumber;
  147. this.numerator = Math.round(this.numerator / factor);
  148. this.denominator = Math.round(this.denominator / factor);
  149. }
  150. }
  151. //private static equals(f1: Fraction, f2: Fraction): boolean {
  152. // return <number>f1.numerator * f2.denominator === <number>f2.numerator * f1.denominator;
  153. //}
  154. //
  155. //public static ApproximateFractionFromValue(value: number, epsilonForPrecision: number): Fraction {
  156. // let n: number = 1;
  157. // let d: number = 1;
  158. // let fraction: number = n / d;
  159. // while (Math.abs(fraction - value) > epsilonForPrecision) {
  160. // if (fraction < value) {
  161. // n++;
  162. // }
  163. // else {
  164. // d++;
  165. // n = <number>Math.round(value * d);
  166. // }
  167. // fraction = n / <number>d;
  168. // }
  169. // return new Fraction(n, d);
  170. //}
  171. //public static GetEarlierTimestamp(m1: Fraction, m2: Fraction): Fraction {
  172. // if (m1 < m2)
  173. // return m1;
  174. // else return m2;
  175. //}
  176. //public CompareTo(obj: Object): number {
  177. // if (this > <Fraction>obj)
  178. // return 1;
  179. // else if (this <<Fraction>obj)
  180. // return -1;
  181. // return 0;
  182. //}
  183. //public static getFraction(value: number, denominatorPrecision: number): Fraction {
  184. // let numerator: number = <number>Math.round(value / (1.0 / denominatorPrecision));
  185. // return new Fraction(numerator, denominatorPrecision);
  186. //}
  187. //public static fractionMin(f1: Fraction, f2: Fraction): Fraction {
  188. // if (f1 < f2)
  189. // return f1;
  190. // else return f2;
  191. //}
  192. //public static fractionMax(f1: Fraction, f2: Fraction): Fraction {
  193. // if (f1 > f2)
  194. // return f1;
  195. // else return f2;
  196. //}
  197. //public static GetMaxValue(): Fraction {
  198. // return new Fraction(Fraction.maximumAllowedNumber, 1);
  199. //}
  200. //public static get MaxAllowedNumerator(): number {
  201. // return Fraction.maximumAllowedNumber;
  202. //}
  203. //public static get MaxAllowedDenominator(): number {
  204. // return Fraction.maximumAllowedNumber;
  205. //}
  206. public ToString(): string {
  207. return this.numerator + "/" + this.denominator;
  208. }
  209. //public ToFloatingString(): string {
  210. // return this.RealValue.ToString();
  211. //}
  212. //public Compare(x: Fraction, y: Fraction): number {
  213. // if (x > y)
  214. // return 1;
  215. // if (x < y)
  216. // return -1;
  217. // return 0;
  218. //}
  219. //#region operators
  220. //
  221. // // operator overloads must always come in pairs
  222. // // operator overload +
  223. // public static Fraction operator + (Fraction f1, Fraction f2)
  224. //{
  225. // Fraction sum = new Fraction(f1);
  226. // sum.Add(f2);
  227. // return sum;
  228. //}
  229. //
  230. //// operator overload -
  231. //public static Fraction operator - (Fraction f1, Fraction f2)
  232. //{
  233. // Fraction diff = new Fraction(f1);
  234. // diff.Sub(f2);
  235. // return diff;
  236. //}
  237. //
  238. //// operator overloads must always come in pairs
  239. //// operator overload >
  240. //public static bool operator > (Fraction f1, Fraction f2)
  241. //{
  242. // //return (long) f1.Numerator*f2._denominator > (long) f2._numerator*f1._denominator;
  243. // return f1.RealValue > f2.RealValue;
  244. //}
  245. //
  246. //// operator overload <
  247. //public static bool operator < (Fraction f1, Fraction f2)
  248. //{
  249. // //return (long) f1._numerator*f2._denominator < (long) f2._numerator*f1._denominator;
  250. // return f1.RealValue < f2.RealValue;
  251. //}
  252. //
  253. //// operator overload ==
  254. //public static bool operator == (Fraction f1, Fraction f2)
  255. //{
  256. // // code enhanced for performance
  257. // // System.Object.ReferenceEquals(f1, null) is better than if (f1 == null)
  258. // // and comparisons between booleans are quick
  259. // bool f1IsNull = System.Object.ReferenceEquals(f1, null);
  260. // bool f2IsNull = System.Object.ReferenceEquals(f2, null);
  261. //
  262. // // method returns true when both are null, false when only the first is null, otherwise the result of equals
  263. // if (f1IsNull != f2IsNull)
  264. // return false;
  265. //
  266. // if (f1IsNull /*&& f2IsNull*/)
  267. // return true;
  268. //
  269. // return equals(f1, f2);
  270. //}
  271. //
  272. //// operator overload !=
  273. //public static bool operator != (Fraction f1, Fraction f2)
  274. //{
  275. // return (!(f1 == f2));
  276. //}
  277. //
  278. //// operator overload >=
  279. //public static bool operator >= (Fraction f1, Fraction f2)
  280. //{
  281. // return (!(f1 < f2));
  282. //}
  283. //
  284. //// operator overload <=
  285. //public static bool operator <= (Fraction f1,Fraction f2)
  286. //{
  287. // return (!(f1 > f2));
  288. //}
  289. //
  290. //public static Fraction operator / (Fraction f, int i)
  291. //{
  292. // return new Fraction(f._numerator, f._denominator *= i);
  293. //}
  294. //
  295. //public static Fraction operator / (Fraction f1, Fraction f2)
  296. //{
  297. // var res = new Fraction(f1.Numerator*f2.Denominator, f1.Denominator*f2.Numerator);
  298. // return res.Denominator == 0 ? new Fraction(0, 1) : res;
  299. //}
  300. //
  301. //public static Fraction operator * (Fraction f1, Fraction f2)
  302. //{
  303. // return new Fraction(f1.Numerator*f2.Numerator, f1.Denominator*f2.Denominator);
  304. //}
  305. //
  306. //public static Fraction operator % (Fraction f1, Fraction f2)
  307. //{
  308. // var a = f1/f2;
  309. // return new Fraction(a.Numerator%a.Denominator, a.Denominator)*f2;
  310. //}
  311. //
  312. //#endregion operators
  313. }