Luhn演算法的c#實現

來源:互聯網
上載者:User
ICCID在使用的時候,有的電訊廠商使用18位,有的電訊廠商使用19位(ICCID-C包含一個校正位)。那麼ICCID-C的校正位的演算法通行是採用Luhn演算法。這個演算法只是用於對數字串的輸入錯誤校正,而非安全性檢查。
由於我們的系統中是使用18位的ICCID,為了在Portability系統中與其他電訊廠商相相容,我們將外部傳入的19位的ICC做去末位處理,對於外部系統所需要的19位ICCID-C,我們直接根據Luhn演算法計算出去校正位,加到18位的ICCID後面,返回給客戶系統。
Luhn演算法,由於其目的是為了檢查輸入錯誤,所以該演算法只要能夠做到一個數字串中的某一位元字輸入錯誤,則其校正位不同,那麼校正的功能就能夠實現了。
Luhn演算法的基本描述:從低位(右向左)起,索引為偶數的數字乘以一個值,索引為奇數的數字則保留不變,經過如此處理後,將所有位對應的數值取數字和#sum。如果#sum以0為結尾,則校正位就為0,否則,以模的值減去#sum的末位元字,便為校正值。
Luhn演算法一般隔一行做乘積處理,而且乘數的選擇有一個講究的地方,那就是0-9這10個數字乘以該乘數的結果的數字和不能存在重複的情況。例如,乘數為3,那麼2*3=6(數字和為6),8*3=24(數字和也為6),那麼如果把2誤敲為8,就檢查不出來了,而一般採用倍乘,即乘數為2,2就不會出現這樣的問題。
此外,在模數的時候,也有多種選擇,一般模數10,比較簡單,關於模數取10以外的其他值,也會存在類似於乘數的選擇所帶來的問題,而且模10的使用在兩處都有涉及,一個是數字和,另一個是用模減去數字和的末位元字,模不同,數字和就有可能不同,最終計算出來的校正位也有可能不同,不過這個我沒有做深入研究。這裡面有一個最佳化選擇問題,一般選擇模10隔位2倍加的演算法,這應該是實踐得出的一個較優選擇。

下面是Luhn的演算法的c#實現,該演算法非常簡單,在網上能找到該演算法的樣本描述,c#實現的也找到了一個,但是感覺有點複雜,寫得不太好。我在實現的時候,也固定了模10隔位2倍加,沒有在模和隔位元和倍數上預留指定的空間。
下面是我的實現。

Code
public class Luhn
{
/**//// <summary>
/// Luhn計算模10“隔位2倍加”校正數字
/// </summary>
/// <param name="numberString">numberString</param>
/// <returns></returns>
public int GetCheckDigit(string numberString)
{
    bool valid = isValidNumberString(numberString);
    if (valid == false) throw new ArgumentException("Invalid parameter.","numberString");

    int sum = getMod10Compartment2Sum(numberString);
    return sum%10 == 0 ? 0 : 10 - sum%10;
}
/**//// <summary>
/// 按 Luhn計算模10“隔位2倍加”的演算法來檢驗一個數字串的正確性
/// </summary>
/// <param name="numberStringWithCheckDigit">numberStringWithCheckDigit</param>
/// <returns></returns>
public bool IsValid(string numberStringWithCheckDigit)
{
    bool valid = isValidNumberString(numberStringWithCheckDigit);
    if (valid == false) throw new ArgumentException("Invalid parameter.", "numberStringWithCheckDigit");

    int checkDigit =
    GetCheckDigit(numberStringWithCheckDigit.Substring(0, numberStringWithCheckDigit.Length - 1));
    int lastDigit =
    Convert.ToInt16(numberStringWithCheckDigit[numberStringWithCheckDigit.Length - 1].ToString());
    return lastDigit == checkDigit;
}
/**//// <summary>
/// 計算數值的數字和
/// </summary>
/// <param name="number"></param>
/// <returns></returns>
private static int getDigitsSum(int number)
{
    int sum = 0;
    for (int i = 0; i < number.ToString().Length; i++ )
    {
    sum += Convert.ToInt16(number.ToString()[i].ToString());
    }

    return sum;
}
/**//// <summary>
/// 計算模10“隔位2倍加”的和
/// </summary>
/// <param name="numberString">numberString</param>
/// <returns></returns>
private static int getMod10Compartment2Sum(string numberString)
{
    int sum = 0;
    for (int i = 0; i < numberString.Length; i++)
    {
    int index = numberString.Length - i - 1;
    if (i % 2 == 1) sum += Convert.ToInt16(numberString[index].ToString());
    else sum += getDigitsSum(Convert.ToInt16(numberString[index].ToString()) * 2);
    }

    return sum;
}
/**//// <summary>
/// 檢查輸入的數字串是否合法
/// </summary>
/// <param name="numberString">numberString</param>
/// <returns></returns>
private static bool isValidNumberString(string numberString)
{
    if(string.IsNullOrEmpty( numberString ))
    {
    return false;
    }

    string regextext = @"^[0-9]+$";
    Regex regex = new Regex(regextext, RegexOptions.None);
    return regex.IsMatch(numberString.Trim());
}
}
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.