Skip to content

Commit

Permalink
fix: Fixes issue for large numbers - closing #1
Browse files Browse the repository at this point in the history
  • Loading branch information
ryasmi committed Jan 5, 2023
1 parent 0853ba6 commit 732e838
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
8 changes: 8 additions & 0 deletions src/baseroo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
25 changes: 19 additions & 6 deletions src/baseroo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}

0 comments on commit 732e838

Please sign in to comment.