From 5d6574c6be8fa370ef465bbb0c7c6b31f0cff1f0 Mon Sep 17 00:00:00 2001 From: Lumi Pakkanen Date: Wed, 17 Jan 2024 11:05:51 +0200 Subject: [PATCH] Make fraction defloating strategy more robust --- src/__tests__/fraction.spec.ts | 6 ++++++ src/fraction.ts | 19 +++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/__tests__/fraction.spec.ts b/src/__tests__/fraction.spec.ts index 7ea9203..5a66434 100644 --- a/src/__tests__/fraction.spec.ts +++ b/src/__tests__/fraction.spec.ts @@ -227,4 +227,10 @@ describe('Fraction', () => { 'Numerator above safe limit' ); }); + + it('can convert a problematic float to a fraction', () => { + const x = 0.5717619047619048; + const y = new Fraction(x); + expect(y.valueOf()).toBeCloseTo(x); + }); }); diff --git a/src/fraction.ts b/src/fraction.ts index 69488d0..c6efccb 100644 --- a/src/fraction.ts +++ b/src/fraction.ts @@ -250,13 +250,20 @@ export class Fraction { if (!coefs.length) { throw new Error('Numerator above safe limit'); } - let n = coefs.pop()!; - let d = 1; - while (coefs.length) { - [n, d] = [d + n * coefs.pop()!, n]; + let j = 1; + while (j <= coefs.length) { + let n = coefs[coefs.length - j]; + let d = 1; + for (let i = coefs.length - j - 1; i >= 0; --i) { + [n, d] = [d + n * coefs[i], n]; + } + this.n = n; + this.d = d; + if (n <= Number.MAX_SAFE_INTEGER && d <= Number.MAX_SAFE_INTEGER) { + break; + } + j++; } - this.n = n; - this.d = d; } this.reduce(); }