[Back to

 previous page] [Next Page

 in Series]

Ken Ward's Java Script Tutorial ...

Multiplying Long Numbers

This page deals with multiplying two long numbers. However, very often when we need to multiply we can multiply by a "small" number and do not have to deal with more than one long number.

In this script, the numbers are put in arrays. The two arrays containing the big numbers are multiplied to get the even longer answer. The script deals with multiplying two positive numbers.

On this page:

An example of the running script is below. Enter two numbers (or use the random buttons) and click on the button to get the answer.

Number 1:

Number 2:


Numbers appear here

For instance, I got this:

Answer checks OK
9,924,129.790891545006121103771196924 x
217,772,519,668.5427208139598990367426=
2,161,202,750,080,099,743.8983715933301845735209049155071526355742560997624
Num Digits: 74
js answer=
2161202750080099800
Time: 0.03 seconds

The script first reports that the answer checks out (using casting out nines) and then presents the multiplication. Then it boasts about the number of digits in the answer, in the above, 74. Then it computes the product using standard javascript (originally as a second check) and finally it says how long it took to work out the answer (0.03 seconds).

The actual time may be a bit longer than this because the browser takes a while to draw the window.

The script begins by defining the number base:

var Base = 10000; // The number base

Using a bigger rather than a smaller base makes the script faster. Instead of working out each individual digital sum, it can multiply in groups of 4, in the present case, because the biggest number in each cell of the array will be 9999.

Check Numbers Entered Are In The Right Format

First the script checks the numbers entered to ensure that at most one decimal point exists, and that no non-numbers have been inputted. It does this using the following function:

function checkNumMult(aNum) {

var isOK=0;

var aNum=aNum+"";

//if the number has one or none decimal points, lastIndexOf and indexOf

//will give the same answer

if (aNum.lastIndexOf(".")!=aNum.indexOf("."))

isOK=1;

else

//here a regular expression is used to check for numbers and decimals

if (aNum.match(/[^0-9.]/g))

isOK=2;

return isOK;

}//end of checkNumMult(aNum)

If there is an error in the numbers, the script says why and tells the user which number has the problem.

Using The Function To Check The Numbers

The above function is used in the code like this:

if (checkNumMult(x)>0)

{

switch (checkNumMult(x)) {

case 1:

alert("Too many decimal points in number 1.")

break

case 2:

alert("Some characters aren't numbers in number 1");

break

}//end of switch

}//end of check number 1

if (checkNumMult(y)>0)

{

switch (checkNumMult(y)) {

case 1:

alert("Too many decimal points in number 2.")

break

case 2:

alert("Some characters aren't numbers in number 2");

break

}//end of switch

}//end of check number 1

 

}//end number problem

else //number checks out

{

Because the function returns 0, if everything is OK, 1 for a decimal problem and 2 for a non-number problem the code can tell the user the kind of problem it found, and also where the problem occurred (number 1 or number 2).

If the numbers check out, the code runs after the else above.

Setting Variables

The following are the variables set at the beginning, with comments:

t1=new Date(); //used to calculate start time

aX=new Array(); //holds number x

aY=new Array(); //holds number y

aW=new Array(); //holds the product, x*y

n1=removeCommas(n1); //clean up n1 and n2

n2=removeCommas(n2);

x=n1; //set x and y values

y=n2;

Further variables are set as follows (getDec was used in the subtraction page):

numlen=x.length+y.length;

decXo=getDec(x); //set original decimal position in x and in y

decYo=getDec(y);

decX=decXo; //also set the current holder of the decimal place

decY=decYo;

//remove decimal from x, using plain javascript.

x=x.replace(".","");

//remove decimal from y

y=y.replace(".","");

//initialise decPlace, which is the number of decimals in

//the number with the most decimals

//First just assume x is the number with most decimal places

//If decX isn't longer than decY, then the following will be true

var decPlace=decX;

What we want to do is to make the numbers into integers, multiply them and then put the decimal points back into the numbers. The next bit of the code puts in any trailing zeros which might be needed to correct the numbers.

//Then check which is the correct number

if (decX>decY)

{

decPlace=decX;

//Then check which is the correct number

if (decX>decY)

{

decPlace=decX;

//add zeros to y

//the number of zeros is just the difference between the number of

//decimal places in each number.

//decYo is the number of decimals in the original y number.

for (var i=0;i<(decPlace-decYo);i++)

{

//add a zero at the end

y+="0";

//increment decY, so we keep a record of the decimal position

//in the new number. For instance

// if decYo=2, as in 1.12, then the number is really 112/10^2

//When we add zeros, the position becomes one more

//for each zero we add .. 1.120, decimal is now 3 from the end, or

//the number is really 1120/10^3

//increment decY

decY+=1;

}

}

//add zeros to x, if y has more decimals

//repeat of the above

else

if (decY>decX)

{

decPlace=decY;

//add zeros to x

for (var i=0;i<(decPlace-decXo);i++)

{

x+="0";

decX+=1;

}

}

//otherwise, decPlace is as above

Because we add zeros, the decimal position will change, so we need to increment one or the other of decX and decY, so we know where to put the decimals in the numbers after multiplying.

Putting the Numbers Into The Arrays

The numbers enter the main function as strings from the form on the page. We need to put them into the arrays. First we do this:

xlen=x.length;

ylen=y.length;

cellSize=getLength(Base);

maxSize=Math.ceil(getLength(x)/cellSize)+Math.ceil(getLength(y)/cellSize);

We record the lengths of the strings and compute the cellSize. The cellSize is computed with:

function getLength(num) {

return Math.ceil(Math.log(num)/Math.LN10);

}//end of getLength(num)

The cellSize is the number of digits in each cell. We can say straight away when we know the Base is 10, that each cell holds one digit, and when the Base is 100, it holds 2. But the computer cannot do this easily, so it needs to do a calculation. The length of a number is the log to base 10 of that number. And this is what the function getLength calculates. As the logs in javascript are natural logs, we need to divide the two logs to get the base 10 logarithm.

The following code builds two arrays containing the two numbers as we want them:

//the length of the array (sum of all digits)

//a product cannot have more than this number of digits, but might have one less

//so the sum of the digits in the multiplier and multiplicand is greater than

//or equal to the sum of those in the product.

sumDig=x.length+y.length;

slice=Math.ceil(sumDig/cellSize);

//make an array:

for (i=0;i<=slice;i++)

aX[i]=null; //this avoids lots of zeros in the answer

for (i=0;i<=slice;i++)

aY[i]=null;

for (i=0;i<=2*slice;i++)

aW[i]=null;

//slice is the number of itesm in the array. Each item or cell has cellSize digits

//put the number into the array

for (i=0;i<slice;i++)

{

//we need to fill the array with the right-most numbers at the right of the array

aX[slice-i-1]=(x.substring(x.length-cellSize*(i+1),x.length- cellSize*(i)));

aY[slice-i-1]=(y.substring(y.length-cellSize*(i+1),y.length- cellSize*(i)));

}

The arrays, aX and aY, now contain the numbers we want to multiply. And all that remains is...

Multiplying The Numbers

The multiplication uses junior school long multiplication adapted for the computer, and for javascript in particular.

The code is:

//carry is zero at the start

carry=0;

//slice is the length of the array

for (i=slice-1; i>=0; i--) {

//multiply numbers

for (j=slice-1;j>=0;j--)

{

//prod is the product of the two digits

prod= aX[i]*aY[j];

//add any carry from previous

prod += carry;

//deal with any new carry

if (prod>=Base) {

carry =Math.floor( prod/Base);

prod -= (carry*Base);

}

else

carry = 0;

aW[i+j]+= prod;

if (aW[i+j]>=Base)

{

rem=Math.floor(aW[i+j]/Base)

aW[i+j]-=rem*Base;

carry+=rem;

}

if (aW[i+j]>Base)

{

aW[i+j-1]+=Math.floor(aW[i+j]/Base);

aW[i+j]=aW[i+j]%Base;

}

}//end of for j

}//end of for i

We have now multiplied the two long numbers and the answer lurks in the array aW.

Writing The Answer Into A String

We now write the answer into the string, z. Here we try to avoid writing out empty cells (which should be null) and to ensure that each cell contains the right number of digits, padding it with leading zeros, as necessary:

z="";

for (k=0;k<aW.length;k++)

if (aW[k]!=null) //we kept the nulls!

{

if (

(

(aW[k]+"").length==cellSize)||

(k>aW.length-2)

)

z+=((aW[k]));

else

{

while ((aW[k]+"").length<cellSize)

{

aW[k]='0'+aW[k];

}

z+=((aW[k]));

}

}

Inserting The Decimals In The Right Place

The numbers are at present integers, because we have removed the decimals. Now, we need to put the decimal points back into the numbers:

//put the decimals back in the numbers

decZ=decX+decY;

x=insertDec(x,decX);

y=insertDec(y,decY);

x=addseps(x);

y=addseps(y);

We have already mentioned addseps on the subtraction page. It adds the thousands separators (commas). The following function, insertDec, inserts the decimal point:

function insertDec(num,decPlace) {

var num=num;

var decPlace=decPlace;

ans="";

mess+="num="+num+"; decPlace="+decPlace+"<br>";

if (decPlace>0)

{

ans=num.substring(0,num.length-decPlace)+"."+

num.substring(num.length-decPlace,num.length);

return ans;

}

else

return num;

}//end of insertDec(x,decPlace)

Removing Leading Zeros

This code removes the leading zeros:

//remove leading zeros from answer:

while (z.charAt(0)=="0")

{

z=z.substring(1,z.length);

}

if (z.charAt(0)==".")

z="0"+z;

But if the number begins with a decimal, then a leading zero is added.

Calculating The Time

We have previously created t1, the start time, and we now create t2 and subtract the two times as below:

t2=new Date();

t1=(t2.getTime()-t1.getTime())/1000

Completing The Code

z=insertDec(z,decZ);

//alert("z after insert="+z);

z=addseps(z); 

//check num length

if (checkAns(x,y,ans))

s+="Answer checks OK<br>";

else

s+="Answer error<br>";

//remove trailing zeros from decimals

z=remTrailingZeros(z);

x=remTrailingZeros(x);

y=remTrailingZeros(y);

s+=x+" x <br>"+y+"=<br>";

s+=z+"<br>";

var numDig=z.length;

if (z.indexOf(".")>-1)

numDig-=1;

s+="Num Digits: "+numDig+"<br>";

s+=("js answer=<br>"+(Number(n1)*Number(n2))+"<br>");

s+="Time: "+t1+" seconds";

document.getElementById("s1").innerHTML=s;

}//else number checks

}

Remove Trailing Zeros

function remTrailingZeros(x) {

var decPos=x.indexOf(".")

if (decPos>-1)

{

first=x.substring(0,decPos);

second=x.substring(decPos,x.length);

while (second.charAt(second.length-1)=="0")

second=second.substring(0,second.length-1);

if (second.length>1)

return first+second;

else

return first;

}

return x;

}//end of remTrailingZeros(x)