Cyclic Redundancy Check or CRC is a method of detecting accidental changes/errors in the communication channel. CRC uses Generator Polynomial which is available on both sender and receiver side. An example generator polynomial is of the form like x3 + x + 1. This generator polynomial represents key 1011. Another example is x2 + 1 that represents key 101. There are two primary variables in CRC:
n: Number of bits in data to be sent from sender side
k: Number of bits in the key obtained from generator polynomial.
Encoded Data Generation from Generator Polynomial (Sender Side)
The binary data is first augmented by adding k-1 zeros in the end of the data.
Then, modulo - 2 binary division is used to divide binary data by the key and remainder of division is stored.
At last the the remainder is appended at the end of the data to form the encoded data which is later sent.
Checking Error in Transmission (Receiver Side)
After receiving the data, to check if the data is error free, perform the modulo-2 division again.
If the remainder is 0, then there are not errors, otherwise, the data is faulty and contain transmission errors.
Modulo 2 Division
The process of modulo-2 binary division is the same as the familiar division process we use for decimal numbers. Just that instead of subtraction, we use XOR here.
In each step, a copy of the divisor (or data) is XORed with the k bits of the dividend (or key).
The result of the XOR operation (remainder) is (k-1) bits, which is used for the next step after 1 extra bit is pulled down to make it k bits long.
When there are no bits left to pull down, we have a result. The (k-1) bit remainder which is appended at the sender side.
The remainder is 001. Thus the data sent is 100100001.
Receiver Side Let there be an error and code word received at the receiver side 100000001.
As the remainder is not 0, hence there is some error detected in the receiver side.
Implementation of Cyclic Redundancy Check
The idea is to firstly generate the encoded data by appending the remainder of modulo - 2 division of data and key in the given data. Then, repeat the same process for the data received, and if the decoded data contains any '1', then there is some error in transmission, otherwise the correct data is received.
Follow the below given step-by-step process:
Start by appending k-1 zeroes to data to form a new string str, where k is the length of key.
Compute the remainder by calling mod2div with dividend set to str and divisor set to key. In mod2div, first slice dividend to the length of divisor, then repeatedly perform the following:
If the first character of the current slice (tmp) is '1', call findXor with divisor and tmp; otherwise, call findXor with a string of pick zeroes and tmp.
Append the next bit of dividend to the result and increment pick.
The function findXor calculates the XOR of two strings a and b by traversing from index 1 to the end: if corresponding bits are the same, it appends "0" to result, otherwise "1".
After processing the entire dividend, mod2div returns the final remainder. Append this remainder to data to form the encoded codeword.
At the receiver side, extract the first n bits of code and perform mod2div with key to obtain curXor. Then, while cur is not equal to code.size, if curXor’s length is not equal to key’s length, append the next bit from code; otherwise, update curXor by performing mod2div on it.
Finally, if curXor’s length equals key’s length, perform a final mod2div. If curXor contains any '1', the data is incorrect; otherwise, the data is correct.
Below is given the implementation:
C++
#include<bits/stdc++.h>usingnamespacestd;// Performs bitwise XOR between two binary strings (a and b)stringfindXor(stringa,stringb){intn=b.length();stringresult="";// Compare each bit (skip first bit as per CRC standard)for(inti=1;i<n;i++){if(a[i]==b[i])result+="0";elseresult+="1";}returnresult;}// Performs Modulo-2 division (CRC division algorithm)stringmod2div(stringdividend,stringdivisor){intn=dividend.length();intpick=divisor.length();stringtmp=dividend.substr(0,pick);// Initial windowwhile(pick<n){if(tmp[0]=='1')// XOR with divisor and bring down next bittmp=findXor(divisor,tmp)+dividend[pick];else// XOR with zeros and bring down next bittmp=findXor(string(pick,'0'),tmp)+dividend[pick];pick++;}// Final XOR stepif(tmp[0]=='1')tmp=findXor(divisor,tmp);elsetmp=findXor(string(pick,'0'),tmp);returntmp;}// Appends CRC remainder to the original datastringencodeData(stringdata,stringkey){intn=key.length();stringpaddedData=data+string(n-1,'0');// Append n-1 zerosstringremainder=mod2div(paddedData,key);returndata+remainder;// Return data + CRC}// Checks if received data has errors (remainder = 0)intreceiver(stringcode,stringkey){stringremainder=mod2div(code,key);return(remainder.find('1')==string::npos)?1:0;}intmain(){stringdata="100100";stringkey="1101";cout<<"Sender Side"<<endl;cout<<"Data: "<<data<<endl;cout<<"Key: "<<key<<endl;stringcode=encodeData(data,key);cout<<"Encoded Data: "<<code<<endl<<endl;cout<<"Receiver Side"<<endl;if(receiver(code,key))cout<<"Data is correct (No errors detected)"<<endl;elsecout<<"Data is incorrect (Error detected)"<<endl;return0;}
Java
importjava.util.*;classGfG{// Returns XOR of 'a' and 'b' (bitwise comparison)staticStringfindXor(Stringa,Stringb){intn=b.length();StringBuilderresult=newStringBuilder();// Compare each bit (skip first bit as per original logic)for(inti=1;i<n;i++){if(a.charAt(i)==b.charAt(i)){result.append('0');}else{result.append('1');}}returnresult.toString();}// Performs Modulo-2 division (CRC division)staticStringmod2div(Stringdividend,Stringdivisor){intn=dividend.length();intpick=divisor.length();Stringtmp=dividend.substring(0,pick);while(pick<n){if(tmp.charAt(0)=='1'){// XOR with divisor and bring down next bittmp=findXor(divisor,tmp)+dividend.charAt(pick);}else{// XOR with zeros and bring down next bittmp=findXor(String.format("%0"+pick+"d",0),tmp)+dividend.charAt(pick);}pick+=1;}// Final XOR stepif(tmp.charAt(0)=='1'){tmp=findXor(divisor,tmp);}else{tmp=findXor(String.format("%0"+pick+"d",0),tmp);}returntmp;}// Appends CRC remainder to original datapublicstaticStringencodeData(Stringdata,Stringkey){intn=key.length();Stringstr=data+String.join("",Collections.nCopies(n-1,"0"));Stringremainder=mod2div(str,key);returndata+remainder;}// Checks if received data has errorspublicstaticintreceiver(Stringcode,Stringkey){Stringremainder=mod2div(code,key);returnremainder.contains("1")?0:1;}publicstaticvoidmain(String[]args){Stringdata="100100";Stringkey="1101";System.out.println("Sender Side");System.out.println("Data: "+data);System.out.println("Key: "+key);Stringcode=encodeData(data,key);System.out.println("Encoded Data: "+code+"\n");System.out.println("Receiver Side");if(receiver(code,key)==1){System.out.println("Data is correct (No errors detected)");}else{System.out.println("Data is incorrect (Error detected)");}}}
Python
deffindXor(a,b):#Performs bitwise XOR between two binary strings (a and b).n=len(b)result=""foriinrange(1,n):# Skip first bit (CRC standard)result+='0'ifa[i]==b[i]else'1'returnresultdefmod2div(dividend,divisor):# Performs Modulo-2 division (CRC division algorithm).n=len(dividend)pick=len(divisor)tmp=dividend[0:pick]# Initial windowwhilepick<n:iftmp[0]=='1':# XOR with divisor and bring down next bittmp=findXor(divisor,tmp)+dividend[pick]else:# XOR with zeros and bring down next bittmp=findXor('0'*pick,tmp)+dividend[pick]pick+=1# Final XOR stepiftmp[0]=='1':tmp=findXor(divisor,tmp)else:tmp=findXor('0'*pick,tmp)returntmpdefencodeData(data,key):# Appends CRC remainder to the original data.n=len(key)# Append n-1 zerospadded_data=data+'0'*(n-1)remainder=mod2div(padded_data,key)# Return data + CRCreturndata+remainderdefreceiver(code,key):# Checks if received data has errors (remainder = 0).remainder=mod2div(code,key)return1if'1'notinremainderelse0if__name__=="__main__":data="100100"key="1101"print("Sender Side")print("Data:",data)print("Key:",key)code=encodeData(data,key)print("Encoded Data:",code,"\n")print("Receiver Side")ifreceiver(code,key):print("Data is correct (No errors detected)")else:print("Data is incorrect (Error detected)")
C#
usingSystem;usingSystem.Text;classGfG{// Returns XOR of 'a' and 'b' (bitwise comparison)privatestaticstringFindXor(stringa,stringb){intn=b.Length;StringBuilderresult=newStringBuilder();// Compare each bit (skip first bit as per original// logic)for(inti=1;i<n;i++){if(a[i]==b[i]){result.Append('0');}else{result.Append('1');}}returnresult.ToString();}// Performs Modulo-2 division (CRC division)staticstringMod2Div(stringdividend,stringdivisor){intn=dividend.Length;intpick=divisor.Length;stringtmp=dividend.Substring(0,pick);while(pick<n){if(tmp[0]=='1'){// XOR with divisor and bring down next bittmp=FindXor(divisor,tmp)+dividend[pick];}else{// XOR with zeros and bring down next bittmp=FindXor(newstring('0',pick),tmp)+dividend[pick];}pick+=1;}// Final XOR stepif(tmp[0]=='1'){tmp=FindXor(divisor,tmp);}else{tmp=FindXor(newstring('0',pick),tmp);}returntmp;}// Appends CRC remainder to original datapublicstaticstringEncodeData(stringdata,stringkey){intn=key.Length;stringstr=data+newstring('0',n-1);stringremainder=Mod2Div(str,key);returndata+remainder;}// Checks if received data has errorspublicstaticintReceiver(stringcode,stringkey){stringremainder=Mod2Div(code,key);returnremainder.Contains("1")?0:1;}staticvoidMain(){stringdata="100100";stringkey="1101";Console.WriteLine("Sender Side");Console.WriteLine("Data: "+data);Console.WriteLine("Key: "+key);stringcode=EncodeData(data,key);Console.WriteLine("Encoded Data: "+code+"\n");Console.WriteLine("Receiver Side");if(Receiver(code,key)==1){Console.WriteLine("Data is correct (No errors detected)");}else{Console.WriteLine("Data is incorrect (Error detected)");}}}
JavaScript
// Performs bitwise XOR between two binary strings (a and b)functionfindXor(a,b){letn=b.length;letresult="";for(leti=1;i<n;i++){// Skip first bit (CRC standard)result+=(a[i]===b[i])?"0":"1";}returnresult;}// Performs Modulo-2 division (CRC division algorithm)functionmod2div(dividend,divisor){letn=dividend.length;letpick=divisor.length;lettmp=dividend.substring(0,pick);while(pick<n){if(tmp[0]==="1"){// XOR with divisor and bring down next bittmp=findXor(divisor,tmp)+dividend[pick];}else{// XOR with zeros and bring down next bittmp=findXor("0".repeat(pick),tmp)+dividend[pick];}pick++;}// Final XOR stepif(tmp[0]==="1"){tmp=findXor(divisor,tmp);}else{tmp=findXor("0".repeat(pick),tmp);}returntmp;}// Appends CRC remainder to the original datafunctionencodeData(data,key){constn=key.length;// Append n-1 zerosconstpaddedData=data+"0".repeat(n-1);constremainder=mod2div(paddedData,key);// Return data + CRCreturndata+remainder;}// Checks if received data has errors (remainder = 0)functionreceiver(code,key){constremainder=mod2div(code,key);returnremainder.includes("1")?0:1;}// Driver Codeconstdata="100100";constkey="1101";console.log("Sender Side");console.log("Data:",data);console.log("Key:",key);constcode=encodeData(data,key);console.log("Encoded Data:",code,"\n");console.log("Receiver Side");if(receiver(code,key)){console.log("Data is correct (No errors detected)");}else{console.log("Data is incorrect (Error detected)");}
Output
Sender Side
Data: 100100
Key: 1101
Encoded Data: 100100001
Receiver Side
Data is correct (No errors detected)
CRC Implementation Using Bit Manipulation - O(n) Time and O(n) Space
The idea is to manipulate the given binary strings by converting them to decimal numbers, and process them. After processing the numbers, convert them back to binary strings.
Follow the below given step-by-step approach:
Determine n as key.length() and convert key to decimal using toDec(key) to get gen, and convert data to decimal using toDec(data) to get code.
Append n-1 zeroes to data by left-shifting code by (n - 1) and store the result in dividend.
Compute shft as ceill(log2l(dividend + 1)) - n, which represents the number of least significant bits not involved in the XOR operation.
While (dividend >= gen) or (shft >= 0):
Calculate rem as (dividend >> shft) XOR gen.
Update dividend by combining the unchanged lower shft bits (dividend & ((1 << shft) - 1)) with the new bits (rem << shft) resulting from the XOR operation.
Recalculate shft as ceil(log2l(dividend + 1)) - n.
After the loop, compute codeword as the bitwise OR of (code << (n - 1)) and dividend.
Finally, output the remainder (obtained by converting dividend to binary using toBin(dividend)) and the codeword (obtained by converting codeword to binary using toBin(codeword)).
C++
#include<iostream>#include<string>#include<cmath>#include<algorithm>usingnamespacestd;#define int long long int // Function to convert integer to binary stringstringtoBin(intnum){// Handle case when number is 0if(num==0)return"0";stringbin="";while(num){// Append '1' or '0' based on least significant bitbin+=(num&1)?'1':'0';// Shift right to process next bitnum=num>>1;}// Reverse string since bits were added in reverse orderreverse(bin.begin(),bin.end());returnbin;}// Function to convert binary string to decimal integerinttoDec(stringbin){intn=bin.size();// Handle empty stringif(n==0)return0;intnum=0;for(inti=0;i<n;i++){if(bin[i]=='1'){// Compute power of 2 for each '1' in binary stringnum+=1<<(n-i-1);}}returnnum;}// Function to compute CRC and print remainder and codewordvoidCRC(stringdata,stringkey){intn=key.length();if(n==0){cout<<"Error: Key cannot be empty"<<endl;return;}// Convert binary strings to decimal integers// Generator polynomial (key)intgen=toDec(key);// Original dataintcode=toDec(data);// Append (n - 1) zeros to the data to make space for CRC bitsintdividend=code<<(n-1);// Calculate the position to start XOR (most significant bit position)intshft;while((shft=(int)log2(dividend)-n+1)>=0){// Extract top 'n' bits of dividend, XOR with generator polynomialintrem=(dividend>>shft)^gen;// Replace top bits in dividend with XOR result (remainder)dividend=(dividend&((1<<shft)-1))|(rem<<shft);}// Final codeword is the original data with the remainder appendedintcodeword=(code<<(n-1))|dividend;// Print resultscout<<"Remainder: "<<toBin(dividend)<<endl;cout<<"Codeword : "<<toBin(codeword)<<endl;}signedmain(){stringdata="100100";stringkey="1101";CRC(data,key);return0;}
Java
importjava.util.Collections;classGfG{// Function to convert integer to binary stringpublicstaticStringtoBin(intnum){// Handle case when number is 0if(num==0)return"0";StringBuilderbin=newStringBuilder();while(num!=0){// Append '1' or '0' based on least significant bitbin.append((num&1)==1?'1':'0');// Shift right to process next bitnum=num>>1;}// Reverse string since bits were added in reverse orderreturnbin.reverse().toString();}// Function to convert binary string to decimal integerpublicstaticinttoDec(Stringbin){intn=bin.length();// Handle empty stringif(n==0)return0;intnum=0;for(inti=0;i<n;i++){if(bin.charAt(i)=='1'){// Compute power of 2 for each '1' in binary stringnum+=1<<(n-i-1);}}returnnum;}// Function to compute CRC and print remainder and codewordpublicstaticvoidCRC(Stringdata,Stringkey){intn=key.length();if(n==0){System.out.println("Error: Key cannot be empty");return;}// Convert binary strings to decimal integers// Generator polynomial (key)intgen=toDec(key);// Original dataintcode=toDec(data);// Append (n - 1) zeros to the data to make space for CRC bitsintdividend=code<<(n-1);// Calculate the position to start XOR (most significant bit position)intshft;while((shft=(int)(Math.log(dividend)/Math.log(2))-n+1)>=0){// Extract top 'n' bits of dividend, XOR with generator polynomialintrem=(dividend>>shft)^gen;// Replace top bits in dividend with XOR result (remainder)dividend=(dividend&((1<<shft)-1))|(rem<<shft);}// Final codeword is the original data with the remainder appendedintcodeword=(code<<(n-1))|dividend;// Print resultsSystem.out.println("Remainder: "+toBin(dividend));System.out.println("Codeword : "+toBin(codeword));}publicstaticvoidmain(String[]args){Stringdata="100100";Stringkey="1101";CRC(data,key);}}
Python
deftoBin(num):"""Convert integer to binary string"""ifnum==0:return"0"bin_str=""whilenum:# Append '1' or '0' based on least significant bitbin_str+='1'ifnum&1else'0'# Shift right to process next bitnum=num>>1# Reverse string since bits were added in reverse orderreturnbin_str[::-1]deftoDec(bin_str):"""Convert binary string to decimal integer"""n=len(bin_str)ifn==0:return0num=0foriinrange(n):ifbin_str[i]=='1':# Compute power of 2 for each '1' in binary stringnum+=1<<(n-i-1)returnnumdefCRC(data,key):"""Compute CRC and print remainder and codeword"""n=len(key)ifn==0:print("Error: Key cannot be empty")return# Convert binary strings to decimal integersgen=toDec(key)# Generator polynomial (key)code=toDec(data)# Original data# Append (n - 1) zeros to the data to make space for CRC bitsdividend=code<<(n-1)# Calculate the position to start XOR (most significant bit position)shft=0whileTrue:current_shft=dividend.bit_length()-nifcurrent_shft<0:break# Extract top 'n' bits of dividend, XOR with generator polynomialrem=(dividend>>current_shft)^gen# Replace top bits in dividend with XOR result (remainder)dividend=(dividend&((1<<current_shft)-1))|(rem<<current_shft)# Final codeword is the original data with the remainder appendedcodeword=(code<<(n-1))|dividend# Print resultsprint(f"Remainder: {toBin(dividend)}")print(f"Codeword : {toBin(codeword)}")if__name__=="__main__":data="100100"key="1101"CRC(data,key)
C#
usingSystem;usingSystem.Text;classGfG{// Function to convert integer to binary stringstaticstringtoBin(intnum){// Handle case when number is 0if(num==0)return"0";StringBuilderbin=newStringBuilder();while(num!=0){// Append '1' or '0' based on least significant bitbin.Append((num&1)==1?'1':'0');// Shift right to process next bitnum=num>>1;}// Reverse string since bits were added in reverse orderchar[]charArray=bin.ToString().ToCharArray();Array.Reverse(charArray);returnnewstring(charArray);}// Function to convert binary string to decimal integerstaticinttoDec(stringbin){intn=bin.Length;// Handle empty stringif(n==0)return0;intnum=0;for(inti=0;i<n;i++){if(bin[i]=='1'){// Compute power of 2 for each '1' in binary stringnum+=1<<(n-i-1);}}returnnum;}// Function to compute CRC and print remainder and codewordstaticvoidCRC(stringdata,stringkey){intn=key.Length;if(n==0){Console.WriteLine("Error: Key cannot be empty");return;}// Convert binary strings to decimal integers// Generator polynomial (key)intgen=toDec(key);// Original dataintcode=toDec(data);// Append (n - 1) zeros to the data to make space for CRC bitsintdividend=code<<(n-1);// Calculate the position to start XOR (most significant bit position)intshft;while((shft=(int)(Math.Log(dividend,2))-n+1)>=0){// Extract top 'n' bits of dividend, XOR with generator polynomialintrem=(dividend>>shft)^gen;// Replace top bits in dividend with XOR result (remainder)dividend=(dividend&((1<<shft)-1))|(rem<<shft);}// Final codeword is the original data with the remainder appendedintcodeword=(code<<(n-1))|dividend;// Print resultsConsole.WriteLine("Remainder: "+toBin(dividend));Console.WriteLine("Codeword : "+toBin(codeword));}staticvoidMain(){stringdata="100100";stringkey="1101";CRC(data,key);}}
JavaScript
functiontoBin(num){// Convert integer to binary stringif(num===0)return"0";letbin="";while(num>0){// Append '1' or '0' based on least significant bitbin=(num&1?"1":"0")+bin;// Shift right to process next bitnum=num>>>1;}returnbin||"0";}functiontoDec(bin){// Convert binary string to decimal integerconstn=bin.length;if(n===0)return0;letnum=0;for(leti=0;i<n;i++){if(bin[i]==='1'){// Compute power of 2 for each '1' in binary stringnum+=1<<(n-i-1);}}returnnum;}functionCRC(data,key){// Compute CRC and print remainder and codewordconstn=key.length;if(n===0){console.log("Error: Key cannot be empty");return;}// Convert binary strings to decimal integers// Generator polynomial (key)constgen=toDec(key);// Original dataconstcode=toDec(data);// Append (n - 1) zeros to the data to make space for CRC bitsletdividend=code<<(n-1);// Calculate the position to start XOR (most significant bit position)letshft;while((shft=Math.floor(Math.log2(dividend))-n+1)>=0){// Extract top 'n' bits of dividend, XOR with generator polynomialconstrem=(dividend>>shft)^gen;// Replace top bits in dividend with XOR result (remainder)dividend=(dividend&((1<<shft)-1))|(rem<<shft);}// Final codeword is the original data with the remainder appendedconstcodeword=(code<<(n-1))|dividend;// Print resultsconsole.log(`Remainder: ${toBin(dividend)}`);console.log(`Codeword : ${toBin(codeword)}`);}// Driver Codeconstdata="100100";constkey="1101";CRC(data,key);
We use cookies to ensure you have the best browsing experience on our website. By using our site, you
acknowledge that you have read and understood our
Cookie Policy &
Privacy Policy
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.