108 lines
2.7 KiB
TypeScript
108 lines
2.7 KiB
TypeScript
export function gcd(a: number, b: number): number {
|
|
a = Math.abs(a);
|
|
b = Math.abs(b);
|
|
while (b) {
|
|
[a, b] = [b, a % b];
|
|
}
|
|
return a;
|
|
}
|
|
|
|
export function lcm(a: number, b: number): number {
|
|
return Math.abs(a * b) / gcd(a, b);
|
|
}
|
|
|
|
export function simplify(num: number, den: number): [number, number] {
|
|
if (den === 0) return [num, den];
|
|
const g = gcd(Math.abs(num), Math.abs(den));
|
|
const sign = den < 0 ? -1 : 1;
|
|
return [(num / g) * sign, (den / g) * sign];
|
|
}
|
|
|
|
export function add(
|
|
n1: number, d1: number,
|
|
n2: number, d2: number,
|
|
): [number, number] {
|
|
const num = n1 * d2 + n2 * d1;
|
|
const den = d1 * d2;
|
|
return simplify(num, den);
|
|
}
|
|
|
|
export function subtract(
|
|
n1: number, d1: number,
|
|
n2: number, d2: number,
|
|
): [number, number] {
|
|
const num = n1 * d2 - n2 * d1;
|
|
const den = d1 * d2;
|
|
return simplify(num, den);
|
|
}
|
|
|
|
export function multiply(
|
|
n1: number, d1: number,
|
|
n2: number, d2: number,
|
|
): [number, number] {
|
|
return simplify(n1 * n2, d1 * d2);
|
|
}
|
|
|
|
export function divide(
|
|
n1: number, d1: number,
|
|
n2: number, d2: number,
|
|
): [number, number] {
|
|
return simplify(n1 * d2, d1 * n2);
|
|
}
|
|
|
|
export function toDecimal(num: number, den: number): number {
|
|
return num / den;
|
|
}
|
|
|
|
export function fromDecimal(decimal: number, precision: number = 6): [number, number] {
|
|
const str = decimal.toFixed(precision);
|
|
const parts = str.split(".");
|
|
if (!parts[1]) return [parseInt(parts[0]), 1];
|
|
const den = Math.pow(10, parts[1].length);
|
|
const num = Math.round(decimal * den);
|
|
return simplify(num, den);
|
|
}
|
|
|
|
export function compare(
|
|
n1: number, d1: number,
|
|
n2: number, d2: number,
|
|
): -1 | 0 | 1 {
|
|
const diff = n1 * d2 - n2 * d1;
|
|
if (diff > 0) return 1;
|
|
if (diff < 0) return -1;
|
|
return 0;
|
|
}
|
|
|
|
export function fractionOfQuantity(num: number, den: number, quantity: number): number {
|
|
return (num / den) * quantity;
|
|
}
|
|
|
|
export function wholeFromFraction(num: number, den: number, part: number): number {
|
|
return (part * den) / num;
|
|
}
|
|
|
|
export function isProper(num: number, den: number): boolean {
|
|
return Math.abs(num) < Math.abs(den);
|
|
}
|
|
|
|
export function toMixed(num: number, den: number): [number, number, number] {
|
|
const whole = Math.floor(Math.abs(num) / Math.abs(den));
|
|
const remainder = Math.abs(num) % Math.abs(den);
|
|
const sign = (num < 0) !== (den < 0) ? -1 : 1;
|
|
return [whole * sign, remainder, Math.abs(den)];
|
|
}
|
|
|
|
export function fromMixed(whole: number, num: number, den: number): [number, number] {
|
|
const sign = whole < 0 ? -1 : 1;
|
|
return [sign * (Math.abs(whole) * den + num), den];
|
|
}
|
|
|
|
export function isSimplified(num: number, den: number): boolean {
|
|
return gcd(Math.abs(num), Math.abs(den)) === 1;
|
|
}
|
|
|
|
export function toKatex(num: number, den: number): string {
|
|
if (den === 1) return `${num}`;
|
|
return `\\frac{${num}}{${den}}`;
|
|
}
|