Assembly Language Programming

February 3, 2011

Javascript – Binary To Decimal Conversion

The Javascript/Html code below converts an arbitrarily large string containing a binary, hexadecimal or octal number to a decimal value. Theoretically, the size of the numbers that this code can handle is unlimited. The algorithm that the code uses to do the conversion is the Remainder Method.

The Remainder Method

To convert some value stored in memory to any number system of radix R, just calculate:

Q(i-1)/R  –>  Q(i) and r(i)

– until Q(i) becomes zero for some i=n. Each remainder r(i) gives a digit in the output value, as follows:

Q(R) = r(n)r(n-1) … r(3)r(2)r(1)r(0)

In other words, dividing Q by R will give a remainder r in the range [0, R-1], and this will just be the right most digit in the base R representation of Q.

A simple example. Consider the value 1234, stored in memory as a binary value. A decimal representation of this value is wanted (R=10):

Q=1234, R=10

Q(0) = 1234/10 = 123, and r(0) = 4
Q(1) = 123/10 = 12, and r(1) = 3
Q(2) = 12/10 = 1, and r(2) = 2
Q(3) = 1/10 = 0, and r(3) = 1

Q(R=10) = r(3)r(2)r(1)r(0) = 1234

The Javascript/Html Code

<html>

<head>
<title>Binary To Decimal</title>

<style type="text/css">

textarea, input, p
{
 font-family: "Lucida Console";

 font-size: 11pt;
}

</style>

</head>

<body onload="Reset()">

<h2>Binary To Decimal</h2>

<textarea id="txtInput" rows="12" cols="90"></textarea>

<p>

<input type="button" value="Binary To Decimal" onClick="BinToDec()">

<input type="button" value="Hex To Decimal" onClick="HexToDec()">

<input type="button" value="Octal To Decimal" onClick="OctToDec()">

<input type="button" value="Clear" onClick="Reset()">

</p>

<textarea id="txtHex" rows="12" cols="90"></textarea>

<br><br>

<textarea id="txtOutput" rows="12" cols="90"></textarea>

</body>

<script type="text/javascript">

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

var Input_Arr=[]; // input array: 32 bit unsigned binary values

var glob_R=0; // global remainder

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function Reset()
{
 Input_Arr=[];

 document.getElementById("txtInput").value="Enter a Binary, Octal or Hexadecimal number.";

 document.getElementById("txtHex").value="";

 document.getElementById("txtOutput").value="";
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function Is_GTE_Ten(A)
{
 // Test if the array A is GTE than 10:

 var bGTE=false;

 if((A[0]>>>0) >= 10) bGTE=true;

 if(bGTE==false)
 {
  var i;

  for(i=1;i < A.length;i++)
  {
   if(A[i] != 0)
   {
    bGTE=true;

    break;
   }
  }
 }

 return bGTE;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function IsGreaterThan(A,B)
{
 // Is array A greater than array B:

 var i;

 var bResult=false;

 var min_length=A.length;

 // if A is longer than B, and contains data in these upper
 // elements, then return true:

 if(A.length > B.length)
 {
  min_length=B.length;

  for(i=A.length-1;i>B.length-1;i--)
  {
   if(A[i] != 0) return true;
  }
 }

 // if B is longer than A, and contains data in these upper
 // elements, then return false:

 if(B.length > A.length)
 {
  min_length=A.length;

  for(i=B.length-1;i>A.length-1;i--)
  {
   if(B[i] != 0) return false;
  }
 }

 // test the rest of the array elements:

 for(i=min_length-1;i>=0;i--)
 {
  // this loop will only be completely iterated
  // if A and B are exactly equal:

  if((A[i]>>>0) > (B[i]>>>0))
  {
   bResult=true;

   break;
  }
  else if((A[i]>>>0) < (B[i]>>>0))
  {
   bResult=false;

   break;
  }
 }

 return bResult;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function getMSB(A)
{
 // get the bit position of the MSB of array A:

 var i;

 var msb_index=-1;

 var msb=-1;

 for(i=A.length-1;i>=0;i--)
 {
  if(A[i] != 0)
  {
   msb_index=i;

   break;
  }
 }

 if(msb_index > -1)
 {
  var test_bit=0x80000000;

  for(i=31;i>=0;i--)
  {
   if(test_bit & A[msb_index])
   {
    msb = i + (32*msb_index);

    break;
   }

   test_bit = test_bit >>> 1;
  }
 }

 return msb;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function getIndex(bitPos)
{
 // get the array index of the element containing the bit
 // at bit location bitPos:

 return (bitPos-bitPos%32)/32;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function calcBit(bit_pos)
{
 // set the bit within a 32 bit word that corresponds
 // to the bit location given by bit_pos:

 var bit=1;

 var shift=bit_pos%32;

 if(shift>0) bit = (bit << shift) & 0xffffffff;

 return bit;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function ArraySubtract(A,B)
{
 // Calc: Diff = A - B

 var Diff=[];

 var i,j;

 var min_length=A.length;

 // if A is longer then B:

 if(A.length > B.length)
 {
  min_length=B.length;

  for(i=0;i<A.length;i++) Diff[i]=0;

  for(i=A.length-1;i>B.length-1;i--)
  {
   Diff[i]=A[i];
  }
 } 

 // if B is longer then A:

 if(B.length > A.length)
 {
  min_length=A.length;

  for(i=0;i<B.length;i++) Diff[i]=0;

  for(i=B.length-1;i>A.length-1;i--)
  {
   Diff[i]=B[i];
  }
 } 

 // if A and B are the same length:

 if(A.length == B.length)
 {
  for(i=0;i<A.length;i++) Diff[i]=0;
 }

 // do the subtraction:

 for(i=min_length-1;i>=0;i--)
 {
  if((A[i]>>>0) == (B[i]>>>0)) Diff[i]=0;

  if((A[i]>>>0) > (B[i]>>>0)) Diff[i]=(A[i]>>>0)-(B[i]>>>0);

  if((A[i]>>>0) < (B[i]>>>0))
  {
   // borrow a bit:

   for(j=i+1;j<Diff.length;j++)
   {
    if(Diff[j] != 0)
    {
     Diff[j]=(Diff[j]>>>0)-1;

     break;
    }
    else
    {
     Diff[j]=0xffffffff;
    }
   }

   // the borrowed bit = 1 + 0xffffffff:

   Diff[i]=0xffffffff-(B[i]>>>0);
    
   Diff[i] += 1 + (A[i]>>>0);
  }
 }

 return Diff;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function Calc_Ten_Arr(A)
{
 var i;

 // it is assumed that msb_A >= 3:

 var msb_A=getMSB(A);

 var Ten_Arr=[];

 // initialise the array containing the divisor:

 for(i=0; i <= getIndex(msb_A) ;i++) Ten_Arr[i]=0;

 // the msb of the bit pattern 1010 is aligned
 // with the msb of A:

 Ten_Arr[getIndex(msb_A)] += calcBit(msb_A);

 Ten_Arr[getIndex(msb_A-2)] += calcBit(msb_A-2);

 // if A is not GTE Ten_Arr, right shift Ten_Arr by one bit:

 var bShift=false;

 bShift=IsGreaterThan(Ten_Arr,A);

 if(bShift)
 {
  Ten_Arr[getIndex(msb_A)] = 0;

  Ten_Arr[getIndex(msb_A-2)] = 0;

  // set the bit pattern 1010:

  Ten_Arr[getIndex(msb_A-1)] += calcBit(msb_A-1);

  Ten_Arr[getIndex(msb_A-3)] += calcBit(msb_A-3);
 }

 return Ten_Arr;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function DivideByTen(A)
{
 // divide the array A by 10 and return the quotient and remainder:

 glob_R=0;

 var Q=[];

 // initialise the quotient array to zero:

 for(var i=0;i<=getIndex(getMSB(A));i++)
 {
  Q[i]=0;
 }

 var Ten_Arr=[];

 // track the index of the bits to be set in the quotient:

 // the set_bit_index measures the difference (bit shift) between
 // the msb in Ten_Arr and the msb of ten (1010 in binary):

 var set_bit_index;

 // the set bit:

 var set_bit;

 while(Is_GTE_Ten(A))
 {
  Ten_Arr=Calc_Ten_Arr(A);

  set_bit_index=getMSB(Ten_Arr)-3;

  // subtract the divisor from the dividend and
  // add the set_bit to the quotient:

  A=ArraySubtract(A,Ten_Arr);

  set_bit=calcBit(set_bit_index);

  Q[getIndex(set_bit_index)] += set_bit;
 }

 // A has been reduced until it is less than 10,
 // remainder is in A[0]:

 glob_R=A[0];

 return Q;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function ReadHexInput()
{
 var in_str=document.getElementById("txtInput").value;

 // remove any non-hex chars:

 in_str=in_str.replace(/[^0-9A-Fa-f]{1,}/g,"");

 var nHexWords=0;

 var i;

 var tmp_str="";

 // make the length of the input string divisible by 8:

 var rem = in_str.length % 8;

 if(rem>0)
 {
  rem=8-rem;

  // pad with zeros:

  for(i=0;i<rem;i++)
  {
   tmp_str += "0";
  }

  in_str = tmp_str + in_str;
 }

 document.getElementById("txtInput").value = in_str;

 nHexWords=in_str.length/8;

 var hex_wd_str;

 var start, end;

 // load the hex words into the input array:

 // Hex = 32 bits per array element (8 hex digits):

 Input_Arr=[];

 for(i=0;i<nHexWords;i++)
 {
  start=in_str.length-((i+1)*8);

  end=start+8;

  hex_wd_str=in_str.slice(start,end);

  Input_Arr[i]=parseInt(hex_wd_str,16);
 }
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function ReadOctInput()
{
 var in_str=document.getElementById("txtInput").value;

 // remove any non-oct chars:

 in_str=in_str.replace(/[^0-7]{1,}/g,"");

 var nOctWords=0;

 var i;

 var tmp_str="";

 // make the length of the input string divisible by 8:

 var rem = in_str.length % 8;

 if(rem>0)
 {
  rem=8-rem;

  // pad with zeros:

  for(i=0;i<rem;i++)
  {
   tmp_str += "0";
  }

  in_str = tmp_str + in_str;
 }

 document.getElementById("txtInput").value = in_str;

 nOctWords=in_str.length/8;

 var oct_wd_str;

 var start, end;

 var oct_val=0;

 var offset=0;

 var index=0;

 // map 8 oct digits to 3 bytes in the input array:

 Input_Arr=[];

 for(i=0;i<nOctWords;i++)
 {
  start=in_str.length-((i+1)*8);

  end=start+8;

  oct_wd_str=in_str.slice(start,end);

  oct_val=parseInt(oct_wd_str,8);

  if(offset==0)
  {
   Input_Arr[index] = oct_val; 
  }

  if(offset==1)
  {
   oct_val = (oct_val << 8) & 0xffffff00;

   Input_Arr[index] = (Input_Arr[index] | oct_val) & 0xffffffff;

   index++;	
  }

  if(offset==2)
  {
   Input_Arr[index+1] = oct_val;

   Input_Arr[index+1] = (Input_Arr[index+1]>>>16) & 0xff;

   oct_val = (oct_val << 16) & 0xffff0000;

   Input_Arr[index] = (Input_Arr[index] | oct_val) & 0xffffffff;

   index++;	
  }

  if(offset==3)
  {
   Input_Arr[index+1] = oct_val;

   Input_Arr[index+1] = (Input_Arr[index+1]>>>8) & 0xffff;

   oct_val = (oct_val << 24) & 0xff000000;

   Input_Arr[index] = (Input_Arr[index] | oct_val) & 0xffffffff;

   index++;	
  }

  offset--;

  if(offset < 0) offset=3;
 }
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function ReadBinInput()
{
 var in_str=document.getElementById("txtInput").value;

 // remove any non-bin chars:

 in_str=in_str.replace(/[^0-1]{1,}/g,"");

 // number of 32 bit words

 var nWords=0;

 var i;

 var tmp_str="";

 // make the length of the input string divisible by 32:

 var rem = in_str.length % 32;

 if(rem>0)
 {
  rem=32-rem;

  // pad with zeros:

  for(i=0;i<rem;i++)
  {
   tmp_str += "0";
  }

  in_str = tmp_str + in_str;
 }

 document.getElementById("txtInput").value = in_str;

 nWords=in_str.length/32;

 var wd_str;

 var start, end;

 // load the 32 bit words into the input array:

 // Binary = 32 bits per array element:

 Input_Arr=[];

 for(i=0;i<nWords;i++)
 {
  start=in_str.length-((i+1)*32);

  end=start+32;

  wd_str=in_str.slice(start,end);

  Input_Arr[i]=parseInt(wd_str,2);
 }
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function CalcHexToDec()
{
 var decimal_str="";

 glob_R=0;

 // use the method of remainders to extract the decimal
 // digits from the binary value in memory:

 while(Is_GTE_Ten(Input_Arr))
 {
  Input_Arr=DivideByTen(Input_Arr);

  // after each division by 10, the remainder gives
  // the next digit in the decimal value: 

  // add the digit:

  decimal_str = glob_R.toString(10) + decimal_str;
 }

 // get the last digit:

 glob_R=Input_Arr[0];

 if(glob_R>0) decimal_str = glob_R.toString(10) + decimal_str;
 
 document.getElementById("txtOutput").value=decimal_str;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function PrintHex()
{
 var i;

 var hexstr = "";

 var count = 0; 
 
 for(i=Input_Arr.length-1;i>=0;i--)
 {
  var tstr = (Input_Arr[i]>>>0).toString(16);

  while(tstr.length < 8) tstr = "0" + tstr;

  hexstr += tstr + " ";

  count++;

  if(count == 10)
  {
   count = 0;

   hexstr += "\r\n";
  }	 
 }

 document.getElementById("txtHex").value = hexstr;
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function BinToDec()
{
 ReadBinInput(); 

 PrintHex();

 CalcHexToDec();
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function HexToDec()
{
 ReadHexInput(); 

 PrintHex();

 CalcHexToDec();
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

function OctToDec()
{
 ReadOctInput(); 

 PrintHex();

 CalcHexToDec();
}

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

</script>

</html>
Advertisements

Create a free website or blog at WordPress.com.

%d bloggers like this: