Skip to content

Commit

Permalink
Replace fraction addition implementation with a 1% faster version
Browse files Browse the repository at this point in the history
  • Loading branch information
frostburn committed Feb 28, 2024
1 parent b55d1fc commit e0ddce1
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@
"premonzo-benchmark": "tsc -p tsconfig-benchmark.json",
"monzo-benchmark": "node benchmarks/__benchmarks__/monzo.mark.js",
"preprimes-benchmark": "tsc -p tsconfig-benchmark.json",
"primes-benchmark": "node benchmarks/__benchmarks__/primes.mark.js"
"primes-benchmark": "node benchmarks/__benchmarks__/primes.mark.js",
"prefraction-benchmark": "tsc -p tsconfig-benchmark.json",
"fraction-benchmark": "node benchmarks/__benchmarks__/fraction.mark.js"
},
"engines": {
"node": ">=10.6.0"
Expand Down
48 changes: 48 additions & 0 deletions src/__benchmarks__/fraction.mark.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// @ts-ignore
import Benchmark = require('benchmark');
import {Fraction, gcd, lcm} from '..';

function addWithLcm(self: Fraction, other: Fraction) {
const {s, n, d} = new Fraction(other);
const denominator = lcm(self.d, d);
return new Fraction(
self.s * self.n * (denominator / self.d) + s * n * (denominator / d),
denominator
);
}

function addWithGcd(self: Fraction, other: Fraction) {
const {s, n, d} = new Fraction(other);
const factor = gcd(self.d, d);
const df = d / factor;
return new Fraction(
self.s * self.n * df + s * n * (self.d / factor),
df * self.d
);
}

function randomFraction() {
return new Fraction(
Math.floor(Math.random() * 10000),
Math.floor(Math.random() * 10000) + 1
);
}

const fractionAddSuite = new Benchmark.Suite();
fractionAddSuite
.add('current implementation', () => {
randomFraction().add(randomFraction());
})
.add('old implementation (using lcm)', () => {
addWithLcm(randomFraction(), randomFraction());
})
.add('new implementation (using gcd)', () => {
addWithGcd(randomFraction(), randomFraction());
})
.on('cycle', (event: {target: any}) => {
console.log(String(event.target));
})
.on('complete', () => {
console.log('Fastest is ' + fractionAddSuite.filter('fastest').map('name'));
})
.run({async: true});
14 changes: 8 additions & 6 deletions src/fraction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,10 +481,11 @@ export class Fraction {
add(other: FractionValue) {
const {s, n, d} = new Fraction(other);
// Must pre-reduce to avoid blowing the limits
const denominator = lcm(this.d, d);
const factor = gcd(this.d, d);
const df = d / factor;
return new Fraction(
this.s * this.n * (denominator / this.d) + s * n * (denominator / d),
denominator
this.s * this.n * df + s * n * (this.d / factor),
df * this.d
);
}

Expand All @@ -496,10 +497,11 @@ export class Fraction {
sub(other: FractionValue) {
const {s, n, d} = new Fraction(other);
// Must pre-reduce to avoid blowing the limits
const denominator = lcm(this.d, d);
const factor = gcd(this.d, d);
const df = d / factor;
return new Fraction(
this.s * this.n * (denominator / this.d) - s * n * (denominator / d),
denominator
this.s * this.n * df - s * n * (this.d / factor),
df * this.d
);
}

Expand Down

0 comments on commit e0ddce1

Please sign in to comment.