@ericrovell/radix

Radix is JavaScript library for radix transformations and manipulations.

Usage no npm install needed!

<script type="module">
  import ericrovellRadix from 'https://cdn.skypack.dev/@ericrovell/radix';
</script>

README

Abacus as symbol of representing numbers in different bases

Radix

Radix is JavaScript library for radix transformations and manipulations.

Motivation

Technical

JavaScript already has the utility function to parse and transform numbers between different radix. But it has the limitations:

  • radix value should be in range [ 2, 36 ];
  • JS integers has safe treshold as 2^53 - 1.

Of course, it is possible to use BigInt instead, but coercion between numbers and BigInts are not that great.

In this library numbers are represented by ranks as an array items [ 1, 2, 3 ] // same as 123 what makes it easier to work with such limitation.

Personal

The main reason for this package for exist, there are plans for small educational webapp for learning numeral bases and this package will be used here. You can see the example project here, it is a bit old and full of bugs. I have decided to do it better from scratch and the work begins here as a little package that might be usefull for someone else too.

Getting started

The package is available via npm:

npm i @ericrovell/radix
import { radix } from "@ericrovell/radix";

radix([ 1, 0, 1, 0], 2).asDecimal // -> 10

API

Constructor

radix(ranks = [ 0 ], radix = 2)

Constructs a number from given ranks and specified radix. The input is validated, more about the validation rules in .valid property description.

In case of invalid input the fallback is number 0 in binary system.

radix().asDecimal                           // -> 0
radix([ 1, 0, 0 ]).asDecimal                // -> 4
radix([ 1, 0, 0, 1, 1, 0, 1 ], 2).asDecimal // -> 77
radix([ 5, 0 ], 2).asDecimal                // -> 0, invalid input

Properties

.valid

Returns the boolean indicating whether or not the input was valid.

Radix should be positive integer equal or larger than 2. Unary base system's are not supported. It complicated the code too much and too primitive to be practical.

Each rank should be non-negative integer and have a value less than radix.

radix([ 1, 1, 0 ], 2).valid    // -> true
radix([ 0, 1, 2, 8 ], 8).valid // -> false, rank can't be 8 for the base 8
radix([ 1, 1, 0 ], 2).valid    // -> true
radix([ 1, 1, 0 ], 1.5).valid  // -> false, radix should be an integer
radix([ 0, 1, 2, 8 ], 0).valid // -> false, radix should be a positive integer
.radix

Returns number's radix value.

radix([ 1, 0, 1], 2).radix // -> 2
.ranks

Returns ranks the number consists of.

radix([ 1, 0, 1], 2).ranks // -> [ 1, 0, 1 ]
.asDecimal

Returns the numeric decimal representation.

radix([ 1, 0, 1, 0 ], 2).asDecimal // -> 10
radix([ 2, 4, 5 ], 8).asDecimal    // -> 165

Manipulations

.number(radix = 10, sep = "")

Constructs a number's string representation with specified radix.

radix([ 1, 0, 1, 0 ], 2).number()       // -> "10"
radix([ 1, 0, 1, 0 ], 2).number(8)      // -> "12"
radix([ 1, 0, 1, 0 ], 2).number(8, ",") // -> "1,2"
.setRadix(radix)

Changes the number's radix and returns a new Radix instance.

radix([ 1, 0, 1, 0 ], 2).setRadix(10) // [ 1, 0 ]
radix([ 1, 0, 1, 0 ], 2).setRadix(8)  // [ 1, 2 ]
radix([ 1, 0, 1, 0 ], 2).setRadix(2)  // [ 1, 0, 1, 0 ]

// shortcuts
radix([ 1, 0 ], 10).binary         // [ 1, 0, 1, 0 ]
radix([ 1, 0 ], 10).octal          // [ 1, 2 ]
radix([ 1, 0 ], 2).decimal         // [ 2 ]
radix([ 1, 0 ], 10).hexadecimal    // [ 10 ]
radix([ 1, 2, 3 ], 10).sexagesimal // [ 7, 11 ]

The are also some shortcut properties for most used radix transformations.

radix([ 1, 0 ], 10).binary         // [ 1, 0, 1, 0 ]
radix([ 1, 0 ], 10).octal          // [ 1, 2 ]
radix([ 1, 0 ], 2).decimal         // [ 2 ]
radix([ 1, 0 ], 10).hexadecimal    // [ 10 ]
radix([ 1, 2, 3 ], 10).sexagesimal // [ 7, 11 ]
.setRank(value = 0, rank = 0)

Changes the value of specific rank and returns the number as new Radix instance.

radix([ 1, 0, 1 ], 2).setRank(0).ranks                      // -> [ 1, 0, 0 ]);
radix([ 1, 0, 1 ], 2).setRank(1, 1).ranks                   // -> [ 1, 1, 1 ]);
radix([ 4, 0, 5, 7 ], 8).setRank(7, 3).ranks                // -> [ 7, 0, 5, 7 ]);
radix([ 1, 0, 1, 0, 1, 1, 1, 0, 1 ], 2).setRank(1, 5).ranks // -> [ 1, 0, 1, 1, 1, 1, 1, 0, 1 ]);

Note: remember, that ranks and array indexes have the reversed order. Ranks order increments to the left:

123 = 1 * 10^2 + 2 * 10^1 + 3 * 10^0

Extending functionality

To extend functionality for your needs, just extend the Radix class available at the root path:

import { Radix } from "@ericrovell/radix";

class RadixExtended extends Radix {
  constructor(ranks, radix) {
    super();
    // ...
  }

  sum() {
    return this.digits.reduce(( acc, digit ) => acc + digit, 0);
  }
}

const extended = new RadixExtended([ 1, 0, 1, 0 ], 2);
extended.sum() // -> 2

Roadmap

  • input validation;
  • ranks mutations;
  • arithmetics;
  • more versatile input;
  • user defined ranks dictionaries;