diff options
Diffstat (limited to 'web/src/math/Ratio.ts')
| -rw-r--r-- | web/src/math/Ratio.ts | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/web/src/math/Ratio.ts b/web/src/math/Ratio.ts new file mode 100644 index 0000000..4973ff4 --- /dev/null +++ b/web/src/math/Ratio.ts @@ -0,0 +1,61 @@ +/** Serializable representation of a ratio. */ +export type RatioData = [numerator: number, denominator: number]; + +/** Representation of a ratio for performing fractional artithmetic. */ +export default class Ratio { + private readonly _numerator: number; + private readonly _denominator: number; + + get numerator(): number { + return this._numerator; + } + + get denominator(): number { + return this._denominator; + } + + constructor(numerator: number, denominator: number) { + if (!Number.isInteger(numerator) || !Number.isInteger(denominator)) { + throw new TypeError( + `Ratio must have integer parts: ${numerator} / ${denominator}`, + ); + } + + if (denominator === 0) { + throw new RangeError("Ratio demnominator cannot be zero"); + } + + this._numerator = numerator; + this._denominator = denominator; + } + + multiplyRatio(other: Ratio): Ratio { + return new Ratio( + this.numerator * other.numerator, + this.denominator * other.denominator, + ); + } + + divideRatio(other: Ratio): Ratio { + return new Ratio( + this.numerator * other.denominator, + this.denominator * other.numerator, + ); + } + + toNumber(): number { + return this.numerator / this.denominator; + } + + static fromInteger(n: number): Ratio { + return new Ratio(n, 1); + } + + toData(): RatioData { + return [this.numerator, this.denominator]; + } + + static fromData(ratio: RatioData): Ratio { + return new Ratio(ratio[0], ratio[1]); + } +} |
