Luhn alqoritmi

**Luhn alqoritmi** — ABŞ alimi Hans Peter Luhn tərəfindən yaradılmışdır. Alqoritm Kredit kartlarınının, IMEI nömrələrinin doğruluğunu yoxlamaq üçün yaradılmışdır. Kredit kartlarının 16 rəqəmli Buraxıcı identifikasiya nömrəsi (Eng:Issuer identification number) olur və hər bir kartın özünəməxsus xüsusiyyətləri olur. Məsələn Visa kartları 4 rəqəmi ilə, MasterCardlar 51–55 ilə başlamalıdır.

IIN mömrələrinin gerçəkliyini yoxlamaq üçün Lhun alqoritmindən istifadə edirlər.

Bu alqoritm hal-hazırda ən çox online satış mağazalarında istifadə olunur, kredit kartlarının doğruluğunu İnternet üzərindən Banka sorğu göndərməklə də təyin etmək olur amma bu alqoritm (Lhun) daha sürətli işləməyə imkan verir.

## Alqoritmin işləmə prinsipi
Alqortimin işləmə prinspini nümunə üzərində göstərək.

16 rəqəmli kredit kartı nömrəmiz olsun.

**1234** — **5678** — **9012** — **3459**

# Cüt indeksdə yerləşən ədələri toplayırıq => (2+4+6+8+0+2+4+9=**35**)
# Tək indeksdə yerləşən ədədləri 2-ə vururuq => (2=6=10=14=18=2=6=10)
# 2-ə vurduğumuz ədələrin rəqəmlərinin cəmin tapırıq => (2+6+(1+0)+(1+4)+(1+8)+2+6+(1+0)=**32**
## 2-ə vurduqdan sonra alınan nəticə 9 dan böyük olarsa həmin ədəddən 9 çıxaraq rəqəmlərin cəmini almış olarıq. 14 rəqəmi üçün: 1 + 4 = 5  14–9 = 5
# Altda və üstə tapdığımız ədədləri toplayırıq => (35 + 32 = 67)
# Ən son tapdığımız ədədi 10-a bölürük => (67 / 10 = 6.7)

**Əgər 10-a tam bölünürsə o zaman bu nömrələr keçərlidir (yəni bir kredit kartına aiddir).**

Alqorimin işləməsinə şəkil üzərində baxaq.

## Proqramlaşdırma Dillərində Təsviri

### Pascal

```pascal
function CheckLuhn(purportedCC: String): Boolean;
var
  i: Integer;
  Sum: Integer;
  Digit: Integer;
begin
  Sum := 0;
  for i := Length( purportedCC ) downto 1 do begin
    Digit := Ord( purportedCC[ i ] ) - Ord( '0' );
if Odd( i ) then
 Inc( Summ, Digit )
else
 Inc( Summ, Digit*2 mod 10 );
  end;
  Result := Summ mod 10 = 0;
end;
```


### Python Proqramlaşdırma dilində

```python
def luhn_checksum(card_number):
    def digits_of(n):
        return [int(d) for d in str(n)]
    digits = digits_of(card_number)
    odd_digits = digits[-1::-2]
    even_digits = digits[-2::-2]
    checksum = 0
    checksum += sum(odd_digits)
    for d in even_digits:
        checksum += sum(digits_of(d*2))
    return checksum % 10

def is_luhn_valid(card_number):
    return luhn_checksum(card_number) == 0
```


### C++ Proqramlaşdırma dilində

```cpp
#include <iostream>
using namespace std;
 
int toInt(const char c)
{
    return c-'0';
}
 
int confirm( const char *id)
{
    bool is_odd_dgt = true;
    int s = 0;
    const char *cp;
 
    for(cp=id; *cp; cp++);
    while(cp > id) {
        --cp;
        int k = toInt(*cp);
        if (is_odd_dgt) {
            s += k;
        }
        else {
            s += (k!=9)? (2*k)%9 : 9;
        }
	is_odd_dgt = !is_odd_dgt;
    }
    return 0 == s%10;
}
 
int main( )
{
    const char * t_cases[] = {
        "49927398716",
        "49927398717",
        "1234567812345678",
        "4532138662787834",
        NULL,
    };
    for ( const char **cp = t_cases; *cp; cp++) {
        cout << *cp << ": " << confirm(*cp) << endl;
    }
    return 0;
}
```


### '''Java proqramlaşdırma dilində'''

```java
public class Luhn {
    static boolean checkLuhn(String cardNo) {
        int nDigits = cardNo.length();

        int nSum = 0;
        boolean isSecond = false;
        for (int i = nDigits - 1; i >= 0; i--) {

            int d = cardNo.charAt(i) - '0';

            if (isSecond)
                d = d * 2;

            nSum += d / 10;
            nSum += d % 10;

            isSecond = !isSecond;
        }
        return (nSum % 10 == 0);
    }

    public static void main(String[] args) {
        System.out.println(Luhn.checkLuhn("4035501000000008"));
    }
}
```

```go
// Package luhn daxil edilən kodun Luhn alqortiminə uyğun olub olmadığını yoxlayır
package luhn

// Valid: daxil edilən kodun Luhn alqortiminə uyğun olub olmadığını yoxlayır
func Valid(number string) bool {
	var total, currentNumber int
	var shouldDouble bool

	number = strings.TrimSpace(number)

	if len(number) < 2 {
		return false
	}

	for i := len(number) - 1; i >= 0; i-- {
		if unicode.IsSpace(rune(number[i])) {
			continue
		}

		if !unicode.IsDigit(rune(number[i])) {
			return false
		}

		currentNumber = int(number[i] - '0')

		if shouldDouble {
			currentNumber *= 2
			if currentNumber > 9 {
				currentNumber -= 9
			}
		}
		shouldDouble = !shouldDouble
		total += currentNumber
	}

	return total%10 == 0
}
```


### '''PHP proqramlaşdırma dilində'''

```php
<?php
$cardNumber = "1234 — 5678 — 9012 — 3459";


function luhnCheck($cardNumber)
{
    $cardNumber = preg_replace('/\D|\s/', '', $cardNumber);
    $sum = 0;
    $isEven = true;
    for ($i = 0; $i < strlen($cardNumber); $i++) {
        $digit = (int)$cardNumber[$i];
        if ($isEven) {
            $digit *= 2;
            if ($digit > 9) {
                $digit -= 9;
            }
        }
        $sum += $digit;
        $isEven = !$isEven;
    }
    return $sum % 10 == 0;
}

echo (luhnCheck($cardNumber)) ? "Bu kart nömrəsi luhn alqoritmi ilə təsdiq olunub" : "Bu kart nömrəsi yanlışdır.";
```


## Həmçinin Bax
* Bank card number
* Java dilində proqram kodu və kredit kart nömrəsinin düzgünlüyünün yoxlanması.
* C dilində proqram kodu.