Ken Ward's Java Script Tutorial ...

Long Numbers - Adding

This is the start of a series that deals with doing arithmetic with big numbers. It is
really about how you can do arithmetic with numbers bigger than those which, in this case,
JavaScript can do, which is about 17 digits.

This study aims to add one big number to another. The script will only add two positive
numbers. This is actually logical because otherwise, it would have to do subtraction,
which is the subject of the next page.

I do not claim the code is well written or optimum: only that it is believed to work.

document.write(String(Math.PI).length)

//gives 17

The maximum array size is 4,294,967,295, which means that some
billions of digits in base 10 can be manipulated. Of course, we aren't limited to base 10,
and can use much bigger bases and therefore potentially bigger numbers. But the
practicality of this depends on the browser, computer, etc.

These are two useful words. Precision relates to the number of digits
that are shown and accuracy relates to the degree the number relates to
the true value. So 1/3=0.334444 is more precise (more digits) than 1/3=0.333, but less
accurate.

Example

This page is likely to be of interest to only a few people who are interested in
numbers. Writing the code was somewhat difficult, and took some time.

The secret, if there is one, is that while numbers are limited in the number of digits
which can be displayed, strings and arrays aren't so limited. What we need to do is to put
our numbers into strings or array and do our sums on them.

This page deals with adding and the code can add very large numbers. I don't know the
largest size of numbers which you can add, but it is probably limited by your computer,
rather than anything else.

The following demonstrates the code on this page. Enter a number in both boxes and
click on the add. You can check the accuracy using normal pencil and paper arithmetic. Or
get an idea from window's calculator.

Number 1:

Number 2:

Numbers appear here

While the example numbers aren't that big, (I didn't make them too big because they
become difficult to read on the page) but you can enter numbers of any size.

The first thing you may notice is that the font for the numbers is a bit funny, being
"monospace". The reason for this is so the numbers can be
formatted in our example. It is nearly impossible to do this with a regular font because
the type characters can vary so much from font to font,
and also in any practical use, our formulas would return a number and not a formatted
example as above.

Another thing you might notice is that the numbers are formatted with comma
separators. Of course, the Germans use commas where the English use dots, and the
French use spaces where the English use commas.

Also you may notice that if you enter non-numerical characters or more than one
decimal, then you get an error message. To deal with these issues properly, it would have
been better to control the characters that can be typed into the boxes so the user cannot
make errors. However, the main purpose of this page is to deal with long numbers and
formatting and error correction are secondary.

The way I decided to add the numbers was to add zeros to the one with the least
decimals and then to add them as regular numbers without any decimals. I had therefore to
record the original decimal positions so I could put them back at the end.

To do this I used the following function:

function

getDec(x) {

x=x+

"";

//position of first decimal digit

pos=x.indexOf(

'.')+1;

//if 0, then no decimals (-1+1)

if

(pos>0)

return

x.length-pos;

else

return

0;

}

//end of getDec(x)

The length of the number in the code above includes the decimal point, but when I come
to put the decimal back, the length will be one less.

When we remove the decimal point, we are effectively multiplying the number by however
decimal places there were in the number with the number with the most decimal places.
Later of course, we will replace the decimal point in the correct position. But for now,
we need to add zeros to the number with the least decimal places.

This is the main code, and is what this page is really about. The algorithm is the one
used in the junior school (England) or gradeschool (USA). That is, you line the numbers up
according to the decimal point and, starting at the right, add the numbers, and if the
answer is bigger than ten, add the carry digit to the next number. Unlike the calculators
used later in school, this algorithm works for any numbers, however big.

//begin adding

//set carry to zero.

var

carry=0;

//set the string, s, which will contain the answer

var

s="";

//now add the two numbers:

//work from the right to the left, starting at the length of the longest
string:

//which is always x

in this
code

var

numx,numy;

//numx and numy will hold the digits in
each number to add

for

(var i=xlen-1;i>=0;i--)

{

//only add the y numbers, if there are any left, else we add zero

numy=0;

if

((ylen-xlen+i)>-1)

numy=parseInt(y.charAt(ylen-xlen+i));

//In the above, when ylen-xlen+i=0, we are at the end of the y numbers

//and i=xlen-ylen. For the next i, (i-1), we will be beyond the length of
y, and

//so just add a possible carry in the next place, and thereafter, add only
zeros

//to the longer number, x

//x is always the longest string

numx=parseInt(x.charAt(i));

//add the sum of the numbers and any carry from previously

//we add only the units bit of the number

//10 is the normal base for decimals

s=(numy+numx+carry)%10+s;

//we carry the tens bit of the new number

carry=Math.floor((numy+numx+carry)/10);

}

//end of adding

if

(carry>0)

s=carry+s;

/*

at the end of the first number, x, we might still have something to carry

For instance, 9+9 gives 8, plus a FINAL carry of 1 (in a new place)

9+
9=
18

But:

18+
9
27

... has a normal carry one place from the end, but no carry at the end
(1+1 (carry)=2, no carry

so we add any carry on the front of the string

*/

Essentially, that's it! We add the two numbers, however, big, and get our answer in the
string, s. All that remains is to write out the number. This is only necessary because the
code is a demonstration of adding long numbers, and it seems that the output should be
nicely formatted. As a function to work out sums, it doesn't need such niceties. These
niceties are, however, useful in other applications. Naturally, adding the decimal points
is essential.

In the code below, we add the decimal points as necessary and also comma separators for
the non-decimal numbers. For this, we use functions. Lastly, we swap the numbers, if
necessary to ensure x is the longest number:

Having put the decimal points back into the number, we will add commas to separate the
thousands. The following function puts the commas in. (With slight modification, it could
add dots or spaces to suit the Germans or the French).

function

addseps(x) {

//make x a new variable

var

x=x;

//make x a string

x+=

"";

//or x=String(x);

//iLen is the number of digits before any decimal point

// for 45.123, iLen is 2

//iLen is the length of the number, if no decimals

iLen=x.length;

pos=x.indexOf(

".");

if

(pos>-1) //there are decimals

{

iLen=pos;

}

//add the decimal point

temp=

"";

//add the decimal part to begin

// with 45.123, we add the .123

temp=x.substring(iLen,x.length);

//iLen-1 is the rightmost non-decimal digit (5 in 98745.123)

for

(var i=iLen-1;i>=0;i--)

//we add a separator when the expression (iLen-i-1)%3==0 is true...

//except when i is (iLen-1), or the first digit

//eg (98745.12). i is iLen-1, and the digit pos is next the decimal,

//it is 5. From here, we decrement i...iLen-2, iLen-3, iLen-4 ... when i
is a multiple of

//3, (i=iLen-iLen+4-1). This point is just before the number 7

if

((iLen-i-1)%3==0&&i!=iLen-1)

temp=x.charAt(i)+

","+temp;

else

temp=x.charAt(i)+temp;

return

temp;

}

//end of addseps(x)

The code above is heavily commented. Even so, it might require careful study.

The sum is written using a monospace font, because the width of numbers in regular
fonts is extremely variable. So a typerwiter font was used.

The place where the writing is done is written like this:

<

spanclass="mon"id="s1">Numbers appear here</span>

And the class "mon" is:

<style type="text/css">

<!--

.mon

{font-family:monospace}

-->

</style>

Here I used monospace, but there are many typewriter fonts which would suit.

In putting in some spaces, I first added some spaces infront of the smaller number, y,
so it was the same length as the longer number x. Secondly, there was the possibility that
the answer might be one longer than the number x, so this had to be allowed for.

Aligning y to x is easily achieved as below:

//align the numbers by putting a space
infront of the shortest number

for

(var i=0;i<(xlen-ylen);i++)

y=

"&nbsp;"+y;

And making the two numbers x and y align with the answer is equally easy: