Archive for the ‘Chrome Web Apps’ Category

Post

How BigIntegers Work, part 2: Multiplication

In Chrome Web Apps on October 22, 2011 by Matthew

In the last post, I gave an overview of how BigIntegers are stored and how addition and subtraction work. Now it’s time to move up the hyperoperation sequence and and discuss multiplication.

Simple Multiplication

Probably the simplest way to think about multiplication is repeated addition. In other words, 4*5 = 5+5+5+5. Using that definition, it would be trivial to write a multiplication function in terms of addition:

// Assume we've defined "ZERO" and "ONE" constants and a "notZero(n)" function, which are all trivial.
// notZero can be as simple as "return n.sign !== 0".
function multiply(a, b) {
    var product = ZERO;
    while (notZero(a)) {
        product = add(product, b);
        a = subtract(a, ONE);
    }
    return product;
}

Something like the code above would work, but would be extremely slow. Imagine multiplying even relatively small numbers (for a big integer library) like 123,456,789 * 65,128,321. Even optimizing it by making sure a is smaller (remember, order doesn’t matter in multiplication) we would have to run the loop 65,128,321 times, with an addition and subtraction each time. Now imagine two 100 digit numbers! Obviously this won’t work.

Grade School Multiplication

The key thing to remember is that numbers are polynomials. So 123 * 456 is really (1 * 100 + 2 * 10 + 3) * (4 * 100 + 5 * 10 + 6). Simplifying a little more, we get (100 + 20 + 3) * (400 + 50 + 6). Lets leave the right side how it is and add up the terms on the left to get our original 123 back: 123 * (400 + 50 + 6). Now we can use the distributive property and get 123*400 + 123*50 + 123*6 = 49200 + 6150 + 738.

All that is a great flashback to your high school algebra class, but how does it help us? Remember that to multiply by a factor of 10, you just add zeros to the end of the number. If we factor out the power of 10 from each term, we just have to do a couple single-digit multiplications, append some zeros, and do a couple additions. Easy! In fact, this is how you’ve been doing multiplication since grade school.

   123
 x 456
 -----
   738
  615
+492
 =====
 56088

So let’s break down what we’re doing. Starting from the right, take each digit from the bottom number, multiply it by each digit of the top number (also from right to left) and write down the result. I’ve glossed over it so far, but remember if you end up with a two digit number, you have to carry the first digit and add it to the next result. Then you move to the next digit, remembering to “multiply by 10″ by shifting the numbers over to the left each time. Finally, add up all the “partial products” and you have the (hopefully correct) answer!

So, how do we do this in code? I’m glad you asked. Here’s a straightforward implementation (we’ll optimize it slightly by eliminating some of the intermediate steps later):

function multiply(a, b) {
    // To keep track of all the partial products
    var partialProducts = [];

    // For each digit of b
    for (var i = 0; i < b.digits.length; i++) {
        var carry = 0;
        var digit;
        var partial = {sign: 1, digits: []}; // Initialize a new partial product

        // For each digit of a
        for (var 0; j < a.digits.length; j++) {
            digit = (b.digits[i] * a.digits[j]) + carry; // Multiply the digits, adding in any carry
            carry = Math.floor(digit / 10);              // Integer divide by 10 to get the first digit
            partial.digits[j] = digit % 10;              // Mod 10 gets the second digit
        }
        // Don't forget the final carry (if necessary)!
        if (carry > 0) {
            partial.digits[j] = carry;
        }

        // Shift the digits to the left to multiply by the next power of 10
        for (var shift = 0; shift < i; shift++) {
            // Unfortunately, JS's naming is backwards from ours.
            // "array.unshift(0)" pushes a zero into the front of the array, which is what we want
            partial.digits.unshift(0);
        }

        // Append this partial product to the list
        partialProducts.push(partial);
    }

    // Now add up all the partial products
    var product = ZERO;
    for (var i = 0; i < partialProducts.length; i++) {
        product = add(product, partialProducts[i]);
    }

    return product;
}

Whew! That’s pretty long, but fairly simple. For each digit of b, loop through each digit of a, multiplying the digits and storing them in the partial product, then add up the partial products at the end.

It’s also still inefficient for several reasons. It’s much better than the simple “loop and add” function at the beginning but we can do better, and actually shorten the code at the same time.

The Real Algorithm

The problem is all those partial products. Instead of building up a list (taking up a potentially large amount of memory) then adding them up at the end, we can just add in each product as we go. We can also avoid pushing all the zeros in by adjusting how we index into the arrays.

function multiply(a, b) {
    var partial = { sign: a.sign * b.sign, digits: [] }; // digits should be filled with zeros

    // For each digit of b
    for (var i = 0; i < b.digits.length; i++) {
        var carry = 0;
        var digit;

        // For each digit of a
        for (var j = i; j < a.digits.length + i; j++) {
            // Multiply the digits, and add them to the current partial product, along with any carry
            digit = partial.digits[j] + (b.digits[i] * a.digits[j - i]) + carry;
            carry = Math.floor(digit / 10); // New carry
            partial.digits[j] = digit % 10; // Put the result back into the partial product
        }
        // Don't forget the final carry (if necessary)!
        if (carry) {
            digit = partial.digits[j] + carry;
            carry = Math.floor(digit / 10);
            partial.digits[j] = digit % 10;
        }
    }

    // That's it!
    return partial;
}

I didn’t mention it before, but the nice thing about multiplication is that the sign is easy to get right. Because our sign property is a 1 (or zero) with the same sign as the number itself, the resulting sign is just a.sign * b.sign.

Further Optimizations

The last function above, is basically how the BigInteger library does multiplication (except in base 10000000 and, as usual, I’ve skipped over some minor details for clarity). But there are actually more sophisticated algorithms to make multiplying huge numbers faster.

They are mostly based on Karatsuba multiplication, which is a recursive “divide and conquer” algorithm. The added complexity and overhead of recursive function calls makes it slower for “reasonably sized” numbers, so it’s best to use simple long multiplication until you get to some threshold then switch to Karatsuba multiplication. I experimented with supporting it early on and the cutoff was somewhere in the several-thousand-digit range.

Post

How BigIntegers Work, part 1: Storage, Addition, and Subtraction

In Chrome Web Apps on October 19, 2011 by Matthew

The Chrome Scientific Calculator supports “approximate” and “exact” numbers. As a slightly simplified explanation, approximate numbers are represented by native JavaScript floating point numbers. Exact integers are represented by an arbitrary-precision BigInteger class (rational numbers have two BigIntegers for the numerator and denominator).

So how do you do math on arbitrarily large integers in a language that only supports 64-bit floating point numbers? Basically the same way you do math in 3rd grade.

The Basics: Storage

A BigInteger is just a sign and an array of digits, from the least significant to most significant:

// n = -123
var n = {
    sign: -1,
    digits: [3, 2, 1]
};

The digits look backwards, but by storing the digits with the ones place first, they will line up with other numbers correctly even if they have different lengths. The sign can be any of {-1, 0, 1} to represent negative, zero, and positive respectively. In mathematical terms (abbreviating digits to “d”):

n = sign * the sum of each digit times 10 to the "place" power.

If you look at the source, you’ll probably notice that I’m actually using base 10000000, not base 10. I’m using decimal in these examples because it makes things clearer but everything works pretty much exactly the same way in any base. Using a larger base just makes things more efficient because you get 7 digits in each array entry. The examples below are also simplified for demonstration purposes, and don’t handle things like signs and different-sized numbers. Keep in mind too that sign and digits are abbreviated to _s and _d to save a few bytes in the .js file.

OK, so that’s simple enough, but what about operators like addition, subtraction, multiplication, and division? They are pretty much exactly how you would do it by hand. I’ll go through each of them and show how they work. I’ll cover addition and subtraction, then multiplication and division in later posts.

Addition

Here’s how would you add two numbers by hand:

 314159
+  2718
-------
 316877

You stack them up with the ones place lined up. Then you go from right to left, adding each pair of digits. 8+9 = 17, 5+1 = 6, 1+7 = 8, and so on. But the 17 is a problem, because you can only put down one digit in each place, so you have to carry the 1 to the next place. So backing up, we have 9+8 = 17, so write down the 7 and carry the one, then 5+1+1 = 7. That’s one digit so we don’t have to carry anything, so we just have 1+7 = 8 and so on. Pretty simple right? It’s exactly what you’ve been doing since first grade (or whenever).

So how would you do that in JavaScript? Remember we’re storing the digits “backwards” so digits[0] is the right-most/least significant digit. That means the places are already lined up correctly, so we can just loop through them, adding each pair, and keeping track of the carry. For simplicity, I’ll assume that both numbers are positive and we padded the digit arrays with zeros to be the same length. In the actual implementation, any extra digits in one number are handled separately to make it faster.

var c = { sign: 1, digits: [] }; // We'll store the result in c
var carry = 0;                   // Nothing to carry yet
for (var i = 0; i < a.digits.length; i++) {
    c.digits[i] = a.digits[i] + b.digits[i] + carry;
    if (c.digits[i] >= 10) { // Oops, too big.
        carry = 1;           // Set the carry to be added into the next digit
        c.digits[i] -= 10;   // Adjust to be one digit
    }
    else {
        carry = 0;           // It fit, so there's nothing to carry
    }
}
if (carry) { // Don't forget to add the final carry if it's needed
    c.digits[i] = carry;
}

Instead of the if (c.digits[i] < 10) {... statement, we can use the remainder and (integer) division operators:

c.digits[i] = (a.digits[i] + b.digits[i] + carry) % 10;
carry = Math.floor((a.digits[i] + b.digits[i] + carry) / 10);

Since JavaScript numbers are always floating point, we have to use Math.floor to fake integer division.

Subtraction

Subtraction is basically the exact opposite of addition. You loop through each digit and subtract. If the result is negative, borrow a 10 from the next digit. Again, for simplicity we’ll assume the numbers are positive, padded to be the same length, and that a > b (if it’s not, we can force it by playing with the signs).

var c = { sign: 1, digits: [] }; // We'll store the result in c
var borrow = 0;                  // We didn't borrow anything yet
for (var i = 0; i < a.digits.length; i++) {
    c.digits[i] = a.digits[i] - b.digits[i] - borrow;
    if (c.digits[i] < 10) { // Oops, we can't have a negative digit
        borrow = 1;         // We'll borrow 10 from the next pair of digits
        c.digits[i] += 10;  // Add the borrowed 10
    }
    else {
        borrow = 0;         // We don't need to borrow anything
    }
}
// We made sure a < b to make sure we never have to borrow after the last digit, so we're done

With the combination of addition and subtraction, we can handle adding any combination of positive and negative numbers (e.g. to subtract a negative from a positive, pretend both are positive and add them).

In part 2, I’ll cover the multiplication algorithm. Division will come in a later post.

Post

Online Library for Scientific Calculator

In Chrome Web Apps on September 10, 2011 by Matthew Tagged:

A few days ago, I launched a service for the Scientific Calculator app that lets you save and load scripts online and share them with other people. Once you have an account (using your Google account naturally), you can see your own scripts and load them directly from the library dialog in the calculator.

You can also view other people’s libraries online at www.calclibrary.com. At the moment, it’s just some examples I uploaded, but I’m hoping it will end up being a useful resource for extending the functionality of the calculator and for learning from other people’s code. Especially since I haven’t gotten around to writing any tutorials or overviews of the language, other than the reference-type documentation that comes with it.

There’s also a secret way to use the calculator online without installing the Chrome app. There are no links to it at the moment, but it shouldn’t be too hard to find if you look for it. It should even work in other modern browsers, although I haven’t tested it much outside of Chrome. Once I’ve tested it more in other browsers, I’ll probably link to it and make it “official”.

Post

Chrome Calculator

In Chrome Web Apps on July 12, 2011 by Matthew Tagged:

About a month ago I published a scientific calculator app to the Chrome Web Store (and I’m just now getting around to blogging about it).

I was thinking about Chromebooks one day, and realized there was no way I could use one without a good scientific calculator. So I checked the Web Store, and didn’t like any of the existing ones. The best one I could find was the appropriately-named “Calculator” (or ”C∞lculator”), but it appears to only be extendable with JavaScript, not it’s own expression syntax. Most of the others were either way too basic or used Google and Wolfram|Alpha to do their calculations.

So after mucha few minutes of thought, I decided to write my own. I already had a functional programming language I was working on (in JavaScript), so it didn’t take long to get the basic language working.

The (unnamed) language is pretty simple, and still needs a few additions, but it works. It’s a functional language where everything is an expression. It’s mostly what you would expect from a calculator but has a few things that are kind of interesting.

Here’s the download link again, if you want to try it. You’ll need Google Chrome to run it for now, but eventually I’ll probably make an online version that works in other browsers.

Definition operator (or, delayed assignment)

Like Mathematica, you can create lazily-evaluated variables with the := operator. For example:

y := x^2 (x doesn’t have to be defined yet)
= true (always returns true, since we can’t evaluate it yet)
x = 4
= 4
y
= 16
x = sqrt 2
= 1.4142135623730951
y
= 2. (whoa)

It basically creates a function that automatically calls itself whenever you need it. It even closes over the current scope. Here’s a more complex example:

var counter (put counter in scope but don’t define it yet)
= undefined
(function() { var current = 0; counter := (current += 1) })() (just like javascript, this is a way to hide “current” in a private scope)
= true
counter
= 1
counter
= 2
counter * 2
= 6

Operators can be used as functions

Most operators can be converted into functions by prefixing them with a “special” colon operator. For example, :+(1, 2, 3) is equivalent to 1 + 2 + 3. The : operator can also take a literal (:42, which gives you a function that always returns 42) or a variable name (:x, returns x).

There are some interesting non-obvious applications, like :() as a shortcut for the identity function. Or there’s this: adder = :function(y) { x + y }. When applied to a function, the new function created by the : operator implicitly takes an argument, x. Since functions close over the current scope (including their arguments), adder takes x and returns a function that adds it’s argument (y) to x. Here’s an example of how it would be used:

adder = :function(y) { x + y }
= function(x) {function(y) {(x + y)}}
add1 = adder(1)
= function(y) {(x + y)}
add2 = adder(2)
= function(y) {(x + y)}
add1(4)
= 5
add2(4)
= 6

A more common application would be passing operators as arguments to functions like map or reduce:

map(:sqrt, [1, 4, 9])
= [1, 2, 3]

Note that sqrt is an operator (along with sin, cos, ln, etc. basically the standard unary functions) so it needs to be converted to a function.

The future

There’s still a lot that I want to do with it, like a way to save and share libraries of functions with other users, big decimals instead of 64-bit floating point numbers (big integers and fractions are already supported), symbolic math (i.e. a CAS), lots more built-in functions and constants, units, etc. I’m open to other ideas and feedback, so let me know if there’s anything you want to see added or improved.