Four Serious Math Libraries for JavaScript

  October 23, 2013

 

JavaScript performs all its math tasks using floating point math. Using floating point numbers works fine up to a point, but then you encounter rounding errors. If you regularly need high-precision numeric output (such as performing financial or scientific calculations), you need one or more of these libraries.

Some math tasks require extreme precision. Imagine being just a little off when you calculate the trajectory to Mars, causing the spaceship to miss the planet entirely. Or think about how you’d feel if the interest calculation for your mortgage was imprecise (in the bank’s favor) or the ingredients in your prescription were proportioned slightly different from the doctor’s intent (enough to kill you).

Precise math calculations is a requirement for many software applications, but JavaScript and other languages can’t provide such precision without help due to the nature of math and the physics of computer hardware. If you need precise output, then you also need a library that helps you go beyond the usual definition of “precise enough.”

Of course, the basic question that most people rightfully ask about now is why such libraries are necessary at all. The main culprit is rounding errors. Some numbers can’t be represented in some bases. For example, 1/3 presents a problem when working in base 10 because it’s a repeating decimal and there isn’t any way to represent it precisely. There are also irrational numbers such as π (pi—a value of approximately 3.1415926535897932384626433832795 – and that “approximately” is the first intimation of problems for some scientific calculations).

Computer rounding errors are compounded because there’s a difference in base (the range of numbers used to perform a calculation). All computer applications perform math using base 2 (with values of 0 and 1), even though you see the output as a base 10 (with values between 0 and 9) representation. Interestingly enough, even though you can represent 1/10 as 0.1 in base 10, it becomes a repeating number in base 2 (0.000110011…). Plus, JavaScript must also contend with rounding errors introduced by representing all numbers in 64-bit floating point form. Consequently, the act of performing precision math that appears in human readable form is a difficult undertaking.

The approximations you get are quite usable for most purposes. Obtaining the precision output is time consuming, and making an application run a lot slower in order to obtain precision you don’t need doesn’t make sense.

But when it does matter, it really matters. However, finding a true, hard core, JavaScript math library can be a bit vexing. Many offerings don’t actually offer math functionality, even though they’re billed as math libraries. And the math libraries vary greatly in their functionality.

The following libraries help you perform specific kinds of precision math. Perhaps I can save you time in comparing what’s available and appropriate for your own JavaScript applications.

numbers.js

The numbers.js library provides substantial math functionality for server-side use. You can use it to perform tasks in these categories:

  • Basic calculations (such as adding two numbers)
  • Complex numbers
  • Calculus
  • Digital Signal Processing (DSP)
  • Matrix operations
  • Computing prime numbers
  • Statistics
  • Generation calculations (such as Fibonacci)

In order to use numbers.js, you must install it on your server (actually in a Web server folder) and ensure that you have node.js installed on your system. You use node.js to create server-side, not client-side, applications. After you install node.js, you open the node.js command prompt (part of the installed node.js functionality), change directories to wherever you want to access numbers.js (such as a directory on your server), type npm install numbers, and press Enter. You now have the numbers.js library installed on your server for use in server-side JavaScript applications. (There isn’t space in this article to show you how to use node.js in a server application, but there are many excellent resources such as The Node Beginner Book, which has a wonderful Hello World example.)

The documentation with number.js is terrible, which is unfortunate because the library does provide a wealth of functionality. The download page isn’t much help either because it doesn’t provide you with a full list of functions. Follow these steps to see a full list of functions in the current version of numbers.js:

  1. Type node and press Enter at the node.js command prompt. You see a greater than sign (>) appear on screen.
  2. Type var Test = require('numbers'); and press Enter. This action loads the library so you can work with it.
  3. Type console.log(Test); and press Enter. You now see a full hierarchical list of functions as shown in Figure 1.

Four Serious Math Libraries for JavaScript 01

At this point, you can try out some of the functions. For example, let’s say you want to determine whether 5 is a prime number. In this case, you’d type console.log(Test.prime.simple(5)); and press Enter. The result is true, much as you’d expect. To test a specific function, you start with the name of the variable containing the library reference (Test), the name of the calculation module (prime), followed by the name of the function (simple), and end with any required input variables.

Demo: https://github.com/sjkaliski/numbers.js/

Download: Performed through node.js

Documentation: Pretty much non-existent

Numeric Javascript

The Numeric Javascript library focuses on these categories of calculation:

  •     Linear algebra
  •     Complex numbers
  •     Splines
  •     ODE solver
  •     Unconstrained optimization
  •     PDE and sparse linear algebra

Math libraries vary in where they run. Numeric Javascript runs on the client, rather than on the server as numbers.js does. The advantage is speed in performing small calculations; a client-side library typically runs small calculations faster because it doesn’t have to transfer data over the network. However, the disadvantage is that a client-side library doesn’t have easy access to server data when performing large, complex calculations. If your calculation involves heavy usage of server data, you might actually find a server-side library is better.

This is a hosted library, which means that you don’t download anything. In addition, the documentation for this library is unique. You click on one of the math categories and see a page of all the functions that Numeric Javascript provides. You can type values into those functions and see them change right before your eyes. Using this approach helps you create code with precisely the right values. Figure 2 shows an example of the functions on the complex numbers page.

Four Serious Math Libraries for JavaScript 02

When looking at this page, you can change the values in the z = numeric.t(3,4); entry and see the new output immediately on screen. In fact, you can modify the equation. For example, changing it to z = numeric.t(3,4).x; displays just the x output. More important, the page shows precisely how you should use the function in your own code.

To access the hosted site in your own application, you add the requisite script entry to your page. The full version (the one with whitespace to make it human readable) is found at: http://www.numericjs.com/lib/numeric-1.2.6.js

Or you can use the minimum version (the one lacking whitespace and comments) to make things faster. This version is found at:  http://www.numericjs.com/lib/numeric-1.2.6.min.js

Demo: http://www.numericjs.com/

Download: Hosted, none required

Documentation: http://www.numericjs.com/

Tangle

The math library category doesn’t just include those that perform calculations. Part of the problem with creating precision math in JavaScript is the way in which the user interacts with the page that supports the math operation.

Precision already costs you a premium in the form of calculation time. However, adding to that cost by transferring whole page elements back and forth between the client and server makes things worse. The Tangle library helps you create reactive documents—ones that interact with the user in a contextual manner with extremely fast response times. The reactive nature of the page makes it possible for the user to interact with the math functionality in ways that would normally be possible only with a desktop application where everything is localized.

The unique aspect of Tangle is that it provides a simpler way to obtain input from the user. For example, a user might see a numeric value underlined on a page. When the mouse hovers over the value, a small balloon tip saying “drag” appears on screen. The user drags and finds that the value increases or decreases. A more interesting input method displays a graph containing the results of an equation. Moving the line on the graph automatically changes the equation content to match. Figure 3 shows a typical graph application. Notice the circle and associated balloon help where the mouse is hovered, which shows that you can drag the mouse to change the appearance of the graph (and the resulting equation).

Four Serious Math Libraries for JavaScript 03

To use Tangle, you either download the kit or create a series of links to the hosted site. Using the hosted site has the advantage of letting you get updates and fixes immediately and automatically; the downloaded version gives you speed of access and stability. Here are the links for the hosted version:

http://worrydream.com/Tangle/Tangle.js

http://worrydream.com/Tangle/TangleKit/mootools.js

http://worrydream.com/Tangle/TangleKit/sprintf.js

http://worrydream.com/Tangle/TangleKit/BVTouchable.js

http://worrydream.com/Tangle/TangleKit/TangleKit.js

You also need to add styles to define which entries on a page can change. The Tangle CSS file helps you accomplish this task:

<link rel="stylesheet" href="http://worrydream.com/Tangle/TangleKit/TangleKit.css" />

The HTML for this example isn’t attached to a particular element. For example, you could easily put variables in a list, should you want to do so. However, you do need to identify how particular elements interact with Tangle, as shown here.

<p id="DoAddition">

When adding numbers,

<span

data-var="Value1"

data-min="-20"

data-max="20"></span> +

<span

data-var="Value2"

data-min="-20"

data-max="20"></span> =

<span data-var="Result"></span>.

</p>

The container element, <p>, must have an id attribute so that Tangle can locate it on the page. Each variable element requires a data-var attribute with a unique name to identify it as well. When you want to make a variable user changeable, you assign it the TKAdjustableNumber class. The data-min and data-max attributes control the range of numbers that the user can select.

To make everything work, you need to create a script that defines the initial variable values, the actions that take place when a user changes a value, and the container element used to hold the variables. Here’s a simple script that completes the addition of two numbers scenario.

window.addEvent('domready', function ()

{

var model =

{

initialize: function ()

{

this.Value1 = 2;

this.Value2 = 3;

this.Result = 5;

},

update: function ()

{

this.Result = this.Value1 + this.Value2;

}

};

new Tangle(document.getElementById("DoAddition"), model);

});

The example begins by ensuring the page is actually loaded. When the page has completed loading, the code creates a model that defines the initial variable values and what happens during an update. This is a simple example; you could combine Tangle with any of the other math libraries to create incredibly complex update functions, and the updates can occur in multiple stages. The final step is to create the actual Tangle object and to assign the model you’ve defined to the container holding the variables.

Demo: http://worrydream.com/Tangle/

Download: http://worrydream.com/Tangle/download.html

Documentation: http://worrydream.com/Tangle/guide.html and http://worrydream.com/Tangle/reference.html

accounting.js

A number of math libraries accept input of a specific kind or create output to make numbers human-readable. The accounting.js library is a prime example. It helps a developer create pleasing numeric output and it also accepts formatted input. For example, if someone tries to input $100,000.00 to JavaScript, the software complains because it can’t parse such input as a number. Using accounting.js makes it possible for a user to input this sort of information and still have JavaScript accept it as a number.

To use this library, you can either download the code from the site or you can use the hosted version. Here’s the link for the hosted version:  http://josscrowcroft.github.io/accounting.js/accounting.js

This library is solely used to format output and unformat input. As a consequence, it’s really lightweight. The documentation for this library is quite good and using the library is relatively simple. Here’s a script that takes a numeric value and outputs it as a monetary value using the local symbols and formatting methodology.

<p>

This number:

<script>

document.write(accounting.formatMoney(1234567.89));

</script>

should appear as a monetary amount.

</p>

As you can see, there are no objects to create, no weird scripts to provide. All you do is call the requisite function to format the output as needed. Simple doesn’t mean lack of flexibly, however. This library does give you full control over the appearance of the output through the use of optional parameters.

Demo: http://josscrowcroft.github.io/accounting.js/#demo

Download: http://josscrowcroft.github.io/accounting.js/#download

Documentation: http://josscrowcroft.github.io/accounting.js/#documentation

Bottom Line

A single article can’t provide you with a complete list of all the math libraries available. You can probably find a library for most needs. A good place to start such a search is the JSter site or the JS Wiki of math libraries which provide individualized summaries. The two things you need to consider as highest priority are getting the right result and getting that result easily. It doesn’t matter how nice the library is if you don’t get the right result and making things hard only increases the chances of human error.

See also:

[dfads params='groups=937&limit=1&orderby=random']