NullifyNetwork

[ Log On ]

[CodeBlog] Luhn check digit algorithm - by simon at Wed, 31 Mar 2010 10:41:03 GMT

Here's one from my distant past but which may be useful to me at some point today. I can actually see plenty of quicker ways to achieve this but it's also well tested for generating/checking credit card check digits:-

/// <summary>
/// Creates/appends Luhn/Mod10 check digits to a specified numeric string
/// Goes belly up with a text string.
/// </summary>
public class LuhnCheck
{
/// <summary>
/// Initialise the LuhnCheck class with a number
/// </summary>
/// <param name="numberToAddDigitTo">The number to do work on</param>
{
setupok = true;
}
/// <summary>
/// Initialise the LuhnCheck class without a number to start with
/// </summary>
public LuhnCheck()
{
}

/// <summary>
/// The number to work on
/// </summary>
{
get
{
}
set
{
setupok = true;
}
}
private bool setupok = false;

/// <summary>
/// Add the check digit to the string and return the whole string
/// </summary>
/// <returns>The whole string with added check digit</returns>
{
if (setupok)
{
}
else
{
throw new ArgumentException("Please specify the number to add the digit to.");
}
}
/// <summary>
/// Creates a check digit without using it
/// </summary>
/// <returns>The check digit</returns>
public int CreateCheckDigit()
{
if (setupok)
{
}
else
{
throw new ArgumentException("Please specify the number to calculate the digit for.");
}
}
/// <summary>
/// Creates the check digit for a specified numeric string - it does not add it, only calculates it
/// </summary>
/// <param name="numberToAddDigitTo">The number to work the check digit out for</param>
/// <returns>The check digit</returns>
public int CreateCheckDigit(string numberToAddDigitTo)
{
string validChars = "0123456789";
foreach (char c in numberToAddDigitTo)
{
if (!(validChars.IndexOf(c) >= 0))
throw new FormatException("The value passed in was not a valid number");
}

string tocheckdigit = numberToAddDigitTo + "0"; //We add zero to use it to calculate
//the number from the correct point - since we'll be alternating between multiplying it by one or two
int strlen = tocheckdigit.Length;
int ncheck = 0;
int nweight = 1; //this will alternate between one and two
int intermediary = 0;
string tosplit = "";

for (int i = 1; i <= strlen; i++) //loop through the card number string
{
intermediary = nweight * Convert.ToInt32(Convert.ToString(tocheckdigit[strlen - i])); //make intermediary
//be the multiple of the variance and the card number
if (intermediary > 9) //if it's bigger than ten...
{
tosplit = Convert.ToString(intermediary);
//Split the two digits
int firstdigit = Convert.ToInt32(Convert.ToString(tosplit));
int seconddigit = Convert.ToInt32(Convert.ToString(tosplit));
//Then add them together
intermediary = firstdigit + seconddigit;
}
//Add the intermediary result to the rolling total
ncheck += intermediary;
//Change the variance as per the Luhn formula
if (nweight == 2)
{
nweight = 1;
}
else
{
nweight = 2;
}
}
//ncheck now has the total
int remainder = 0;
//Work out the remainder
Math.DivRem(ncheck, 10, out remainder);
//return ten minus the remainder (if it's zero then it divides perfectly by ten so is valid,
//but since we're CREATING a check digit we want to know how far off the result is and how much we
//need to correct it using the check digit)
if (10 - remainder == 10)
{
return 0;
}
else
{
return 10 - remainder;
}

}
/// <summary>
/// Whether the number stored in the object is a valid MOD 10/Luhn check digited number
/// </summary>
public bool IsValid
{
get
{
if (CreateCheckDigit() == 0)
{
return true;
}
else
{
return false;
}
}
}
}