95 lines
3.0 KiB
TypeScript
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);
|
|
});
|
|
});
|