Sunday, May 27, 2012

My first programming: Hamming Code

Last year at SJSU, from computer architecture class, I implemented Hamming code after I studied Java language at SJSU. San Jose State University's most CS classes use Java language, so I studied Java class as soon as I transferred to SJSU. CS 147 was mainly about memory and computer history, but I liked projects my professor assigned because I felt better upon completion of assignments.


Richard Hamming, a theorist with Bell Telephone Laboratories in the 1940s, developed the Hamming code method of error correction in 1949. An error correction method that intersperses several  check bits at the certain situation of the input data bits. At the receiving station, the check bits are used to detect and correct one-bit errors automatically. You are required to implement his method.

Input: Use random generator or manually  to generate a sequence of binary bits and the program will insert the check bits . Then assign a special position which the bit is corrupted. The program will automatically detect the error and correct it.

Method: See the lecture note. Use the even parity check.

You are to try 10 different reference strings with fixed length.
2 strings with length 5
2  strings with length 10
2 strings with length  16
2 strings with length 20
2 strings with length 25.
The  program can check max length up to  30.

For example Test Cases:
(1) Please create the Hamming coded bit sequence for the 5 data bits 01010 (The 5 data bits do not contain the check bit)
(2) Please create the Hamming coded bit sequence for the 16 data bits 0101001101010101? (The 16 data bits do not contain the check bit)
(3) Please create the Hamming coded bit sequence for the 25 data bits 010100110101001 01010101? (The 16 data bits do not contain the check bit)

Display the output as follows:

The length of input string: ???
The input string:??????
The Hamming code:
Error ocurrs at position: ??
The corrupted Hamming code:???????
Detect the error at position: ???


/**
 * @author      Hun Wie <skyhuni82@hotmail.com>
 * @date        2011.04.03
 */

package hammingcode;
import java.util.*;

/**
 *
 * @author Theo
 */
public class Main {
    final static int MAX_SIZE = 100;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Scanner in = new Scanner (System.in);
        boolean isValid = false;
         int convertData1=0;
         byte [] covertDataArray = new byte [MAX_SIZE] ;
         
         int lengthOfData=100;
         String data1="";
         byte data2;
         int twoNumber =0;
         while(lengthOfData > 30){
            int arrayLength=0;
            //check if this is valid input
            while(!isValid){
                try{
                System.out.println("Enter the binary bits");
               
               data1 = in.next();
         
          
                  for ( int i = 0; i < data1.length(); i++)
                {
                    covertDataArray[i] = Byte.parseByte(data1.substring( i, i+1));
                }

          
               
                int base = 2;
                convertData1 = Integer.parseInt(data1, base);
                isValid = true;
                } catch( Exception e) {
                    System.out.println("You must enter an binary inputs");
                }

            }//end of 'while' this is valid input

          
           
              
                int n =  data1.length();
                System.out.println("The length of input String is " + n);
                System.out.print("The input String:");
                for ( int i = 0; i < data1.length(); i++)
                {

                    System.out.print(covertDataArray[i]);
                }
                System.out.println("");
                //TwoNumber : geting the number of Power of Two
                //  TwoNumber = (int) Math.ceil(Math.log(n)/Math.log(2)) + 1;
                if( n >= 1 && n <=4)
                {
                    twoNumber = 3;
                }
                else if ( n > 4 && n <= 11)
                 {
                     twoNumber =4;
                 }
                else if ( n > 11 )
                 {
                     twoNumber =5;
                 }
                 

               
                //lengthOfData : get the total length of two's and data
                lengthOfData = n + twoNumber;
                
                if(lengthOfData > 30)
                {
                    System.out.println("This program can check max length up to 30. "
                            + "Enter the data again");
                    
                }
                
             
        }//end of while
         
         byte [] hammingArray = new byte [lengthOfData];
         boolean powerOfTwo = false;
         int indexNotPowerTwo =0;
         int indexOfHamming = 0;
         int indexOfOri = 0;
         //notPowerTwoArray in base 2 : 3(0011), 5(0101), 6(0110), 7...
         byte[][] notPowerTwoArray = new byte[data1.length()][];
         //notPowerIndexNumber[] : put non power of two into order, 1st(3), 2nd(5), 3rd(6)...[3,5,6,7...]
         int [] notPowerIndexNumber = new int [data1.length()];

         //for : put the data into non power of two position of hamming array
         for (int i = 1; i <= lengthOfData; i++)
         {
             int index =0;
             powerOfTwo = isPowerOfTwo(i);
             if (!powerOfTwo )
             {
                 //hammingArray[i-1] : hamming code store byte into array
                 hammingArray[i-1] = covertDataArray[indexOfOri++]; //covertDataArray data we got
                 // notPowerTwoArray[indexNotPowerTwo] : declaration of notPowerTwoArray size of 5
                 notPowerTwoArray[indexNotPowerTwo] = new byte[5];
                 //notPowerIndex[index] to recall non-Power of Two number to turn base 2 : 3(0011),5(0101),6,7,...
                 //and increment of it
                 notPowerIndexNumber[index++] = indexNotPowerTwo;
                 //turnBaseTwo : turn non-power two number into 2 base byte
                 turnBaseTwo(notPowerTwoArray, i, indexNotPowerTwo );
                 indexNotPowerTwo++;
             }
             else
             {
                 indexOfHamming++;
             }
         }
         //two[] : array of two's
         byte [] two = new byte [twoNumber];

         getTwoPowerPosition(two, twoNumber,notPowerTwoArray, indexNotPowerTwo, covertDataArray);
         insertTwoPowerPosition ( lengthOfData, two, hammingArray);
       
         System.out.print("The hamming code:");
         for (int i = 0; i < lengthOfData; i++)
         {
             System.out.print(hammingArray[i]);
         }
          System.out.println("");
          System.out.print("Error Occurs at position?");
          int error = in.nextInt();

          if (hammingArray[error -1] ==1)
          {
              hammingArray[error -1] = 0;
          }
          else
          {
              hammingArray[error -1] = 1;
          }
        System.out.print("The corrupted Hamming code:");
          for (int i = 0; i < lengthOfData; i++)
         {
             System.out.print(hammingArray[i]);
         }
         System.out.println("");
        

        int errorPosition = detectError(two, twoNumber, notPowerTwoArray,lengthOfData,covertDataArray,data1.length(),hammingArray);
        System.out.println("Detect the error at position:" + errorPosition);
     
      }

/**
 * getTwoPowerPosition method gets the check-bit array

 * @param  TwoNumber length of two's number
 * @param two[] two's array
 * @param notPowerTwoArray[][] byte of non-power of two of base 2,e.g 3(0011), 5(0101), 6(0110), 7...
 * @param dataLength length non power of array
 * @param covertDataArray the data we got in
 *
 */

static void getTwoPowerPosition (byte [] two, int TwoNumber, byte notPowerTwoArray[][], int dataLength,byte covertDataArray[] )
{

    byte m = 0;
    int index = 0;
    int originalDataIndex =0;
        
    
        // for: column of 5 byte, e.g : 00000, 00001, 00011
        for ( int column = 0 ; column < 5; column++)
        {
            // for : row of data
            for ( int row = 0; row < dataLength; row++)
            {
                //check if it is 2'0, 2'1, 2'2 position
                if(notPowerTwoArray[row][column] == 1)
                {
                    // if it is, check if the original data in parity
                    if(covertDataArray[originalDataIndex] == 0 && m == 0)
                    {
                            m = 0;
                            originalDataIndex++; // increase the data index
                    }
                    // exclusive or
                    else if (covertDataArray[originalDataIndex] == 1 && m == 1 )
                    {
                            m = 0;
                           originalDataIndex++; // increase the data index
                    }
                    // if the data and m(check ) is not same, initialize m = 1
                    else
                    {
                            m = 1;
                           originalDataIndex++;
                    }
                }
                // //check if it is not 2'0, 2'1, 2'2 position , increse index for the next position of data
                else
                {
                   originalDataIndex++;
                }
            }
            originalDataIndex =0;

        // two : insert check bit to array
        two[index] =  m;
        // increase the index of check bit array
        if ( index < TwoNumber -1)
        {
            index++;
        }
       else
        {
            ;
        }
        // initialize the m(check) =0;
        m = 0;
    
    }
}


/**
 * isPowerOfTwo method returns true if number is power of two

 * @param  number any number
 * @return true if it is power of two, false if it is not
 *
 */

static boolean isPowerOfTwo(int number){
    boolean isPowerOfTwo = true;
    int reminder = 0;
    while(number > 1){
        reminder = number % 2;
        if(reminder != 0)
        {
            isPowerOfTwo = false;
            break;
         }
        else
        {
            number = number / 2;
        }
    }
    return isPowerOfTwo;
    }

/**
 * turnBaseTwo method turns non power of two number to base 2 e,g 3(0011), 5(0101), 6(0110), 7...

 * @param  notPowerTwoArray[][] byte of non-power of two of base 2,e.g 3(0011), 5(0101), 6(0110), 7...
 * @param numberOfThatposition non power of two position 1st(3),2nd(5)...e.g : [3,5,6,7...]
 * @param indexNotPowerTwo data length
 */
static void turnBaseTwo (byte [][] notPowerTwoArray, int numberOfThatposition, int indexNotPowerTwo)
    {
        int count = 0;
        byte remainder=0;
        int base = 2;
        while (numberOfThatposition >= base)
            {

                remainder = (byte) (numberOfThatposition % base) ;
                notPowerTwoArray[indexNotPowerTwo][count] = remainder;
                count++;
                numberOfThatposition = numberOfThatposition/base;
            }
        notPowerTwoArray[indexNotPowerTwo][count] = (byte) numberOfThatposition;
    }

/**
 * insertTwoPowerPosition method insert power of two position into hamming array

 * @param  hammingArray[] hamming array
 * @param lengthOfData data length]
 * @param two data byte 0 or 1 for power of two e,g, (1)2'0,(2)2'1,(4)2'2, (8)2'3...
 */
static void insertTwoPowerPosition (int lengthOfData, byte two[], byte hammingArray[])
    {
         boolean powerOfTwo = false;
         int index =0;

         for (int i = 1; i <= lengthOfData; i++)
         {

             powerOfTwo = isPowerOfTwo(i);

             if (powerOfTwo)
             {
                  hammingArray[i-1] = two[index];
                  index++;
             }
             else
             {
                ;
              }

          }
    }

/**
 * detectError method detects the error and fixes it and returns the position number

 * @param  TwoNumber length of two's number
 * @param two[] array of byte 0 or 1 for power of two
 * @param notPowerTwoArray[][] byte of non-power of two of base 2,e.g 3(0011), 5(0101), 6(0110), 7...
 * @param dataLength length of data
 * @param covertDataArray the data we got in
 * @param hammingArray[] hamming array
 * @param originalDataLength length of data we got
 * @return errorPosition error position number
 *
 */
 static int detectError (byte [] two, int twoNumber, byte notPowerTwoArray[][], int dataLength,byte covertDataArray[],
         int originalDataLength, byte hammingArray[]){
     
    int errorPosition = 0;
    boolean powerOfTwo = false;
    int indexOfTwo = 0;
    int indexOfData =0;
      //for : get the corrupted hamming code of non power of two to convertDataArray
     for (int i = 1; i <= dataLength; i++)
         {
             
             powerOfTwo = isPowerOfTwo(i);
             if (!powerOfTwo )
             {
                 covertDataArray[indexOfData] = hammingArray[i-1];
                  if (indexOfData < originalDataLength)
                  {
                    indexOfData++;
                  }
                  else
                  {
                    ;
                  }
                
             }
             else
             {
                two[indexOfTwo++] = hammingArray[i-1];

             }
           
         }
    
  

    byte m = 0;
    byte [] error = new byte [twoNumber];
    int index = 0;
    int originalDataIndex =0;
    


    m = two[index];
    // for getting the the Error position
    // put 1 on byte error[] array
        for ( int column = 0 ; column < 5; column++)
        {
            for ( int row = 0; row < originalDataLength; row++)
            {
                if(notPowerTwoArray[row][column] == 1)
                {
                   if(covertDataArray[originalDataIndex] == 1 && m == 1)
                    {
                            m = 0;
                            originalDataIndex++;
                    }
                    else if (covertDataArray[originalDataIndex] == 0 && m == 0 )
                    {
                            m = 0;
                           originalDataIndex++;
                    }

                    else
                    {
                       m = 1;
                       originalDataIndex++;
                    }
                }
                else
                {
                   originalDataIndex++;
                }
            }
            originalDataIndex =0;


        if (m == 0)
        {
            error[index] = 0;
        }
        else
        {
            error[index] = 1;
        }
        if ( index < twoNumber -1)
        {
            index++;
        }
       else
        {
            ;
        }

        m = two[index];

    }

    //for calculation of error position
    for (int i = 0; i < twoNumber; i++)
    {
        if(error[i] == 1)
        {
            errorPosition  += (int) Math.pow(2,i);
        }
    }
    // fixes the corrupted hamming code error
    if (hammingArray[errorPosition -1] ==1)
    {
        hammingArray[errorPosition - 1] = 0;
    }
    else
    {
        hammingArray[errorPosition -1] = 1;
    }
    
    return errorPosition;
}



}

/* output
 * 1st
The length of input String is 5
The input String:01010
The hamming code:010010100
Error Occurs at position?4
The corrupted Hamming code:010110100
Detect the error at position:4
 *
 * 2nd
The length of input String is 5
The input String:11101
The hamming code:101011001
Error Occurs at position?2
The corrupted Hamming code:111011001
Detect the error at position:2
 *
 * 3rd
The length of input String is 10
The input String:1101010010
The hamming code:01111010010010
Error Occurs at position?7
The corrupted Hamming code:01111000010010
Detect the error at position:7
 *
 * 4th
 The length of input String is 10
The input String:1011011101
The hamming code:10100110011101
Error Occurs at position?5
The corrupted Hamming code:10101110011101
Detect the error at position:5
 *
 * 5th
 The length of input String is 16
The input String:1101101100100111
The hamming code:011010101011001100111
Error Occurs at position?10
The corrupted Hamming code:011010101111001100111
Detect the error at position:10
 *
 * 6th
The length of input String is 16
The input String:1110110111010101
The hamming code:111011011101110110101
Error Occurs at position?1
The corrupted Hamming code:011011011101110110101
Detect the error at position:1
 *
 * 7th
 The length of input String is 20
The input String:10110110101010010101
The hamming code:0010011101101010010010101
Error Occurs at position?2
The corrupted Hamming code:0110011101101010010010101
Detect the error at position:2
 *
 * 8th
 The length of input String is 20
The input String:01010010101010010111
The hamming code:0100101100101011010010111
Error Occurs at position?17
The corrupted Hamming code:0100101100101011110010111
Detect the error at position:17
 *
 * 9th
 The length of input String is 25
The input String:1010001010101001010101010
The hamming code:111001000010101001001010101010
Error Occurs at position?24
The corrupted Hamming code:111001000010101001001011101010
Detect the error at position:24
 *
 * 10th
 0101111111111111010101100
The length of input String is 25
The input String:0101111111111111010101100
The hamming code:010010101111111111111010101100
Error Occurs at position?25
The corrupted Hamming code:010010101111111111111010001100
Detect the error at position:25
        */

Since this was my first java assignment out of java class, it did not use OO design that much. It was my first time to create jar file as well. : ) 

2 comments:

  1. Hey, I was strolling through the internet for a good solution for the hamming code problem in java and I found your code, which seemed perfect, until I found a major flaw to it.
    When inputting 4 bit messages, the hamming code it generates has the 4th bit always set to 0. And it's annoying the crap out of me that I can't figure it out.
    Can you replicate this issue and check if it's fixable? :)

    ReplyDelete
  2. I think is is fixable, I will update it.

    ReplyDelete