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

rational-arithmetic

v0.2.2

Published

A no-depndency, lightweight library for arithmetic with rational numbers

Downloads

8

Readme

rational-arithmetic

npm rational-arithmetic Build Status

A no-dependency, lightweight JS library for arithmetic with rational numbers

Rationale

Why another rational numbers library?

There's definitely more than enough rational numbers libraries for JavaScript. I created rational-arithmetic because most of the other libraries I could find didn't have the level of API ergonomics that I desired.

Implementing a class like Rational in Python is great, because it allows custom classes to overload default operators. This is not so in JS, so we need to be smarter about how to expose arithmetic operator APIs and primitive-object conversions in a way that's easy to read and use. This project puts API ergonomics at the top of the list of its priorities.

Features

  • Correct support for infinities
  • Support for primitive JS double precision floating-point values
  • Ergonomic and readable API
  • Support for all JavaScript unary and binary number operators
  • Transparent interoperability with primitive numbers when exact correctness isn't needed

API

Rational class

A rational number is represented as an instance of the Rational class.

But in normal usage, you should very rarely need to use the Rational class directly. Instead, you should use the r function to tag template literals into Rational instances.


const { r } = require('rational-arithmetic');

const r1 = r`12/5`;     // 12 / 5
const r2 = r`2.5`;      // 5 / 2
const r3 = r`-89.123`;  // - 89123 / 1000

The r tag accepts numbers in any format, including integers and floating points with signs, and improper fractions using the / symbol.

If you'd like to construct instances of Rational manually, you can also do so.

The signature for the Rational class constructor is Rational(numerator: number, denominator: number[, sign: 1 or -1]). You can place any JavaScript number primitive into numerator and denominator slots, and they'll be normalized into reduced fractions.

const { Rational } = require('rational-arithmetic');

const r1 = new Rational(12, 5)          // 12 / 5
const r2 = new Rational(10 / 4)         // 5 / 2
const r3 = new Rational(89.123, 1, -1)  // - 89123 / 1000

Instances of the Rational class also have access to 3 other utility methods, normalize(), equal(r), and clone().

normalize() -> Rational (self)

Normalizes the numerator, denominator, and sign of the rational number to a canonical format, by ensuring the following is true:

  • Numerator and denominator share no common factors larger than 1
  • Numerator is a nonnegative integer
  • Denominator is a natural number
  • Sign is either 1 or -1

normalize() mutates the original object, and returns itself.

equal(r: Rational) -> Boolean

Does a deep equality comparison between two instances of Rational. equal(r) compares values after normalization (reducing the fraction).

clone() -> Rational

Returns a new instance of Rational with the same properties as itself.

Arithmetic

rational-arithmetic comes with the following operators. Wherever number is marked as the accepted type, instances of Rational as well as JavaScript number primitives are accepted; all operators will return instances of Rational, even if all operands were primitive.

const {
  r,
  abs,
  add, sub,
  mul, div,
} = require('rational-arithmetic');

abs(r`-23/5`)                 // 23 / 5
add(1, 2, 3)                  // 6
sub(r`7/6`, 2)                // 19 / 6
mul(r`12/7`, -3.5, r`24/16`)  // - 9
div(12, 2.21)                 // 1200 / 221

abs(number) -> Rational

Absolute value operator.

add(...number) -> Rational

Addition operator. add is variadic, and will return the sum of all given arguments. You can mix primitives and Rational numbers as arguments.

sub(number, number) -> Rational

Subtraction operator. Unlike add, sub only ever takes two arguments.

mul(...number) -> Rational

Multiplication operator. mul is variadic, and will return the product of all given arguments. You can mix primitives and Rational numbers as arguments.

div(number, number) -> Rational

Division operator. Unlike mul, div only ever takes two arguments, and returns the quotient as a Rational number.

Compatibility and conversion between primitives and Rational instances

Transparent interoperability between JavaScript primitive values and Rational instances was a key design goal of rational-arithmetic. The library makes interoperation easy and transparent in two cases

Using primitive values in arithmetic operations

When you use primitive numbers in any of the arithmetic operators given as functions here, they'll be transparently promoted to instances of Rational without losing any precision. See the examples above in the Arithmetic section for more examples.

Using Rational instances with native JavaScript operators

When native JavaScript operators like + - / * % or native Math functions like Math.abs() or Math.pow() are used with Rational instances, the double precision approximation for the rational numbers will be used instead, requiring no explicit conversion step.

Infinities and indeterminate (undefined) values

Infinite and indeterminate values are correctly supported in rational-arithmetic. Infinite values are represented internally as

// positive Infinity
Rational {
  sign: 1,
  numerator: Infinity,
  denominator: 1,
}

// or negative Infinity
Rational {
  sign: -1,
  numerator: Infinity,
  denominator: 1,
}

and undefined or indeterminate values (the result of evaluating Infinity / Infinity or 0 / 0) are represented as

// indeterminate value, NaN
Rational {
  sign: 1,
  numerator: NaN,
  denominator: NaN,
}

and these values are canonicalized to NaN when cast to primitive values.

The full list of arithmetic involving infinities follows native ECMAScript conventions, and is as follows:

Infinity / Infinity -> NaN
Infinity / 0 -> Infinity
0 / Infinity -> 0
0 / 0 -> NaN
Infinity / <finite number> -> Infinity
<finite number> / Infinity -> 0

These infinite and indeterminate value representations should interoperate transparently with JavaScript primitive values the way other Rational values do.

Contributing

Found a bug? Please put in a pull request! If you have a feature request, feel free to open an issue, though those aren't guaranteed to be followed-through.

Tests

rational-arithmetic strives for 100% test coverage of exposed interfaces. You can run tests with

yarn test
# or
npm test

and add tests under test/test.js.