raw code

Rational numbers in JavaScript

Robert Eisele

Fraction.js is a rational numbers written in JavaScript. Floating point numbers, like double in JavaScript, are a very rough estimate of a real number, which has to deal with rational and irrational numbers the same way. Of course, it has the benefit of feeling very natural in the way you deal with numbers. You can assign Math.PI, Math.sqrt(2) and 3 / 4 without thinking what the computer actually does.

The obvious downside of the way double is represented inside of the computer is the loss of precision, especially when you only need to deal with ratios.

When we remember some high-school math, we can easily avoid those problems. Introducing some kind of number theory makes the whole thing perfect. That's why I wrote Fraction.js.

Download Fraction.js

Rational Numbers Calculator

123/33 div 4.33
123.(345) mod 3.(1112)

Rational Approximation of Irrational numbers

Assume you want to find a rational approximation of PI. There is a nice algorithm, which doesn't converge very fast, but serves good as an example here.

var PI = new Fraction(0);
var four = new Fraction(4);
var n = 1;
for (var i = 0; i < 100000; i++) {
	PI = PI.add(four.div(n));
	n+= 2;
	PI = PI.sub(four.div(n));
	n+= 2;

The result of this algorithm is

PI.n / PI.d = 17402216385200408 / 5539306332998545 = 3.14158765358987

Looks nice, doesn't it? In the README.md, which is shipped with the library, is another algorithm to approximate sqrt(5) - 2.


So what is it all good for and where are the limits?

The library can be used whenever you have to do precise calculations with natural and rational numbers. Even if you don't use it in production, you can use it to pre-calculate numbers (as I did with PI above).

I tried not to force casting to real integers in the JavaScript source. This would have the limit of the smallest (unsigned) number of 1 / (Math.pow(2, 31) - 1) and the biggest number of (Math.pow(2, 31) - 1) / 1. The way it is implemented now, you work with doubles again - larger doubles, which shrinks the problem space.

Another obvious limit is the fact, that it is bound to rational numbers - as the name suggests. I've implemented a sqrt(n) function, but it is very inprecise, as it only gives an estimate. But in some optimization scenarios this is more than enough.