From 732e838ab08b0cff3ccc129920ac3a14d8505cd4 Mon Sep 17 00:00:00 2001 From: Ryan Smith <3045513+ryansmith94@users.noreply.github.com> Date: Thu, 5 Jan 2023 17:04:23 +0000 Subject: [PATCH] fix: Fixes issue for large numbers - closing #1 --- src/baseroo.test.ts | 8 ++++++++ src/baseroo.ts | 25 +++++++++++++++++++------ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/baseroo.test.ts b/src/baseroo.test.ts index 7ee4b18d..e63401b9 100644 --- a/src/baseroo.test.ts +++ b/src/baseroo.test.ts @@ -21,3 +21,11 @@ test('convertBase should convert an empty input string to 0', () => { const expectedOutput = '0' assert.strictEqual(actualOutput, expectedOutput) }) + +test('convertBase should convert BigInts too', () => { + const input = + '4ef57aa335b86bce90cd99144be26fa47645c36624eeb54ae153bc67861f9a7ad96e23e0d200348bd6a442ef96bd04a2c' + const interimOutput = convertBase(input, 16, 10) + const actualOutput = convertBase(interimOutput, 10, 16) + assert.strictEqual(actualOutput, input) +}) diff --git a/src/baseroo.ts b/src/baseroo.ts index 7ecc2d3e..9b938a22 100644 --- a/src/baseroo.ts +++ b/src/baseroo.ts @@ -6,25 +6,38 @@ export class InvalidDigitError extends BaseError { } } +function bigIntPow(x: bigint, y: bigint): bigint { + const ZERO = BigInt(0) + if (y === ZERO) return BigInt(1) + const TWO = BigInt(2) + const p2 = bigIntPow(x, y / TWO) + if (y % TWO === ZERO) return p2 * p2 + return x * p2 * p2 +} + export function convertBase(value: string, fromBase: number, toBase: number): string { const range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+/'.split('') const fromRange = range.slice(0, fromBase) const toRange = range.slice(0, toBase) + const fromBaseBig = BigInt(fromBase) + const toBaseBig = BigInt(toBase) + let decValue = value .split('') .reverse() - .reduce(function (carry: number, digit: string, index: number): number { - if (fromRange.indexOf(digit) === -1) { + .reduce(function (carry: bigint, digit: string, index: number): bigint { + const fromIndex = fromRange.indexOf(digit) + if (fromIndex === -1) { throw new InvalidDigitError(digit, fromBase) } - return (carry += fromRange.indexOf(digit) * Math.pow(fromBase, index)) - }, 0) + return carry + BigInt(fromIndex) * bigIntPow(fromBaseBig, BigInt(index)) + }, BigInt(0)) let newValue = '' while (decValue > 0) { - newValue = toRange[decValue % toBase] + newValue - decValue = (decValue - (decValue % toBase)) / toBase + newValue = toRange[Number(decValue % toBaseBig)] + newValue + decValue = (decValue - (decValue % toBaseBig)) / toBaseBig } return newValue || '0' }