Files
cabrits-math/lib/math/fractions.test.ts
2026-07-05 11:12:45 -04:00

95 lines
3.0 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { gcd, lcm, Fraction } from "./fractions";
const f = (n: number, d: number) => new Fraction(n, d);
describe("gcd / lcm", () => {
it("computes gcd", () => {
expect(gcd(12, 8)).toBe(4);
expect(gcd(7, 3)).toBe(1);
expect(gcd(0, 5)).toBe(5);
expect(gcd(-12, 8)).toBe(4);
});
it("computes lcm", () => {
expect(lcm(4, 6)).toBe(12);
expect(lcm(3, 5)).toBe(15);
});
});
describe("Fraction sign + simplify", () => {
it("keeps the sign on the numerator", () => {
expect([f(2, -4).n, f(2, -4).d]).toEqual([-2, 4]);
expect([f(-2, -4).n, f(-2, -4).d]).toEqual([2, 4]);
});
it("reduces to lowest terms", () => {
const check = (n: number, d: number, en: number, ed: number) => {
const s = f(n, d).simplified();
expect([s.n, s.d]).toEqual([en, ed]);
};
check(5, 10, 1, 2);
check(8, 12, 2, 3);
check(3, 1, 3, 1);
check(2, -4, -1, 2);
check(-2, -4, 1, 2);
check(0, 5, 0, 1);
});
it("reports whether it is already simplified", () => {
expect(f(1, 2).isSimplified).toBe(true);
expect(f(5, 10).isSimplified).toBe(false);
});
});
describe("Fraction arithmetic (raw, then .simplified())", () => {
const s = (fr: Fraction) => [fr.simplified().n, fr.simplified().d];
it("adds", () => {
expect(s(f(1, 2).plus(f(1, 2)))).toEqual([1, 1]);
expect(s(f(2, 10).plus(f(3, 10)))).toEqual([1, 2]);
expect(s(f(1, 3).plus(f(1, 4)))).toEqual([7, 12]);
});
it("subtracts", () => {
expect(s(f(7, 8).minus(f(6, 8)))).toEqual([1, 8]);
expect(s(f(1, 2).minus(f(1, 2)))).toEqual([0, 1]);
});
it("multiplies", () => {
expect(s(f(2, 3).times(f(3, 4)))).toEqual([1, 2]);
expect(s(f(1, 2).times(f(1, 2)))).toEqual([1, 4]);
});
it("divides (invert and multiply)", () => {
expect(s(f(1, 2).dividedBy(f(1, 4)))).toEqual([2, 1]);
expect(s(f(3, 4).dividedBy(f(1, 2)))).toEqual([3, 2]);
});
it("handles negative fractions with the sign rules", () => {
expect(s(f(-1, 2).plus(f(3, 4)))).toEqual([1, 4]); // -1/2 + 3/4
expect(s(f(1, 2).minus(f(-3, 4)))).toEqual([5, 4]); // subtracting a negative adds
expect(s(f(-2, 3).times(f(1, 4)))).toEqual([-1, 6]); // different signs -> negative
expect(s(f(-2, 3).times(f(-3, 5)))).toEqual([2, 5]); // same signs -> positive
expect(s(f(-1, 2).dividedBy(f(1, 4)))).toEqual([-2, 1]); // -1/2 ÷ 1/4
});
});
describe("Fraction presentation + equality", () => {
it("renders KaTeX, collapsing whole numbers", () => {
expect(f(1, 2).toKatex()).toBe("\\frac{1}{2}");
expect(f(3, 1).toKatex()).toBe("3");
});
it("renders signed KaTeX with the sign in front", () => {
expect(f(-3, 4).toSignedKatex()).toBe("-\\frac{3}{4}");
expect(f(3, 4).toSignedKatex()).toBe("\\frac{3}{4}");
expect(f(-5, 1).toSignedKatex()).toBe("-5");
});
it("compares by value, not written form", () => {
expect(f(5, 10).equals(f(1, 2))).toBe(true);
expect(f(1, 2).equals(f(1, 3))).toBe(false);
});
});