npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ericrovell/radix

v1.1.0

Published

Radix is JavaScript library for radix transformations and manipulations.

Downloads

29

Readme

Radix

Radix is JavaScript library for radix transformations and manipulations.

Features:

  • Extendable;
  • Immutable;
  • No dependencies;
  • Simple API;
  • Types included;
  • Works in a browser and Node.js;

Motivation

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.

This library use ranks array to represent a number: [ 1, 2, 3 ] // same as 123 which makes it easier to work with such limitation. BigInt used for internal calculations so values above safe integer threshold won't be a problem.

Getting started

The package is available via npm:

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

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

API

Constructor

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().decimal                            // -> 0
radix([ 1, 0, 0 ]).decimal                 // -> 4
radix([ 1, 0, 0, 1, 1, 0, 1 ], 2).decimal  // -> 77
radix([ 5, 0 ], 2).decimal                 // -> 0, invalid input

Input options

The valid types of input are:

  • number: Any positive integer number, float values are considered invalid;
  • bigint;
  • string;
  • number[]: Homogeneous array of integer numbers;
  • string[]: Homogeneous array of string symbols;

number and bigint are considered to have the radix = 10, and this radix value is default.

number[] and string[] input decoded first (if such option is passed, more about soon), and after parsed as number ranks.

// integer
radix(132).getRanks(); // -> [ 1, 3, 2 ]

// bigint
radix(456n).getRanks(); // -> [ 4, 5, 6 ]

// string
radix("1234").getRanks(); // -> [ 1, 2, 3, 4 ]

// number[]
radix([ 5, 6, 7, 8 ]).getRanks(); // -> [ 5, 6, 7, 8 ]

// string[]
radix([ "1", "2", "3" ]).getRanks(); // -> [ 1, 2, 3 ]

Options

All constructor options are optional.

To define custom ranks decoding, provide a decodings object:

import type { Decodings } from "@ericrovell/radix";

const decodings: Decodings = {
  "A": 0,
  "B": 1,
};

radix([ "A", "B" ], 2, { decode: decodings }).getRanks(); // -> [ 1, 0 ]

Also, the decoder function can be provided instead:

import type { Decoder } from "@ericrovell/radix";

const decoder: Decoder = rank => rank ? "A" : rank;

radix([ "A", 1 ], 2, { decoder }).getRanks(); // -> [ 0, 1 ]

Sets the minimal number of ranks.

radix([ 1 ], 2, { minRanks: 5 }).getRanks();     // -> [ 0, 0, 0, 0, 1 ]
radix([ 1 ], 2, { minRanks: -5 }).getRanks();    // -> [ 1 ]
radix([ 1, 2, 3, 4 ], 10, { minRanks: 3 }); // -> [ 1, 2, 3, 4 ]

Methods and properties

Returns the numeric decimal representation.

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

Do not use if the decimal value may exceed the safe integer value as it returns Number instance which is not safe. Use .valueOf() instead.

Returns ranks the number consists of.

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

The output may be encoded using the encode argument.

Encoding using the the encodings object:

import type { Encodings } from "@ericrovell/radix";

const binary = {
  0: "A",
  1: "B"
};

radix([ 1, 0, 1, 0 ], 2).toString(binary)  // -> [ "B", "A, "B", "A ]

Encoding using the the encoder function:

import type { Encoder } from "@ericrovell/radix";

const binaryEncoder: Encoder = rank => {
  return rank === 0 ? "A" : "B"
};

radix([ 1, 0, 1, 0 ], 2).toString(binaryEncoder)  // -> [ "B", "A, "B", "A ]

Returns the rank value at specified index.

Index is tied to the rank's power:

$$ 1234 = 1 * 10^3 + 2 * 10^2 + 3 * 10^1 + 4 * 10^0$$

Here, the last rank value 4 has a power of 0, that's how index is calculated.

const number = radix([ 1, 2, 3, 4 ], 10)

number.rank(0); // -> 4
number.rank(3); // -> 1

Returns number's radix value.

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

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

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

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

Note: The index is tied to the power, read more at .getRank() method.

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

Constructs a number's string representation.

radix([ 2, 3, 4 ], 10).toString()       // -> "234"

The custom encoding can be specified using the encodings object or encoder function, same as .getRanks() method.

import type { Encodings, Encoder } from "@ericrovell/radix";

const binary = {
  0: "A",
  1: "B"
};

const binaryEncoder: Encoder = rank => {
  return rank === 0 ? "A" : "B"
};

radix([ 1, 0, 1, 0 ], 2).toString(binary)  // -> "BABA"
radix([ 1, 0, 1, 0 ], 2).toString(binaryEncoder)  // -> "BABA"

To define a separator, provide a second argument:

radix([ 1, 0, 1, 0 ], 2).toString(undefined, "+")  // -> "1+0+1+0"

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. Valid input options are covered here.

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(2.5, 10).valid               // -> false, unsupported input
radix([ 0, "1", 2, 8 ], 10).valid  // -> false, array should be homogeneous

Returns the primitive value as decimal radix BigInt value.

radix([ 2, 3 ], 10).valueOf() // -> 23n

Method may be useful for coercion:

radix([ 1, 2 ], 10) + radix([ 2, 3 ], 10) // -> 35n

Other features

Coercion

The Radix instance supports coercion via toString() and valueOf() methods. The latter returns a bigint decimal representation.

radix([ 1, 2, 3 ], 10) + radix([ 7, 7 ], 10) // 200n

Extedibility

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

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

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

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

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

Iterability

The Radix instance can be iterated via for ... of loop to loop through the ranks in powers order:

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

for (const [ rank, power ] of radix([ 1, 2, 3 ])) {
  console.log(rank, power)
  // -> [ 3, 0 ], [ 2, 1, ], [ 1, 2 ]
}

for (const [ rank, power ] of radix([ 5, 4 ], 10).setRadix(2)) {
  console.log(rank, power)
  // -> [ 0, 0 ], [ 1, 1 ], [ 1, 2 ], [ 0, 3 ], [ 1, 4 ], [ 1, 5 ]
}

The same way the spread operator can be used, Array.from(), and all other methods and functions that operates on iterables.