Konto bankowe w Polsce ma format zgodny ze standardem IBAN (https://pl.wikipedia.org/wiki/Mi%C4%99dzynarodowy_numer_rachunku_bankowego). Zaczyna się od znaków PL (opcjonalnie). Potem dwie cyfry kontrolne po których następuje 24 cyfry właściwego numeru (z czego pierwsze 8 to numer banku).
Napisać algorytm liczenia cyfr kontrolnych dla polskich kont bankowych. .
W Polsce cyfry te liczymy według wzoru: 98 - konto modulo 97, gdzie konto - zamieniona na cyfry reprezentacja konta (zob. poniżej), a modulo = reszta z dzielenia. Zamiana konta na cyfry odbywa się następująco:
Należy napisać prosty algorytm korzystajacy z braku ograniczeń na wielkość liczby całkowitej, a później algorytm operujący na mniejszych liczbach (nie więcej niż 9 cyfr).
Należy założyć, że konto otrzymujemy bez prefiksa (PLcc) i znaków rozdzielających (-).
(konto bez cyfr kontrolnych - cyfry kontrolne) 123456789012345678901234 - 04 230000000123456789012345 - 63 345678900000067890123456 - 15 456789012345600000234567 - 60
Trywialny algorytm zadziała tylko wtedy, gdy język programowania obsłuży bardzo duże liczby (tak jest w Pythonie). Sposób wyliczenia reszty bez operowania na dużych liczbach można znaleźć analizując dzielenie pisemne przez liczby dwucyfrowe. Na pryzkład: Znamy pisemny sposób dzielnia. Na przykład
816345 : 12 = 6 8 02 8
72
...
96
96
...
034
24
...
105
96
...
9
Jak widać za każdym razem bierzemy resztę z dzielenia i dopisujemy jedną lub dwie kolejne cyfry (gdy pierwsza jest zerem). Ale nic nie stoi na przeszkodzie, by zawsze dopisywać więcej niż jedną cyfrę:
816345 : 12 = 6 80 28
72
...
963
960
...
345
336
...
9
Resztę z dzielnia całej liczby zawsze otrzymujemy w ostatnim kroku. W naszym algorytmie założymy, że dopisujemy po 8 cyfr.
Najpierw kod trywialny
class Rozwiazanie(object):
def algorytm(self,konto):
num = int(konto+'252100')
cyfry = 98 - num % 97
if cyfry < 10:
return '0'+str(cyfry)
else:
return str(cyfry)
Algorytm z mniejszymi liczbami (mozna stosować w innych niż Python językach).
class Rozwiazanie2(object):
def algorytm(self,konto):
n1 = int(konto[:8])
c1 = n1 % 97
n2 = int(str(c1)+konto[8:16])
c2 = n2 % 97
n3 = int(str(c2)+konto[16:])
c3 = n3 % 97
n4 = int(str(c3)+'252100')
cyfry = 98 - n4 % 97
if cyfry < 10:
return '0'+str(cyfry)
else:
return str(cyfry)
// przykładowa funkcja w PHP
function iban_checksum($nr) {
$nr1 = substr($nr,0,8);
$checksum = intval($nr1) % 97;
$nr1 = strval($checksum).substr($nr,8,8);
$checksum = intval($nr1) % 97;
$nr1 = strval($checksum).substr($nr,16,8);
$checksum = intval($nr1) % 97;
$nr1 = strval($checksum). "252100"; // PL00 => L=21, ..., P=25.
$checksum = 98 - (intval($nr1) % 97);
if ($checksum<10) {
return '0'.$checksum;
} else {
return ''.$checksum;
}
}
from nose.tools import assert_equal, assert_raises
class Testowanie(object):
parametry = [('123456789012345678901234','04'),
('230000000123456789012345','63'),
('345678900000067890123456','15'),
('456789012345600000234567','60')]
def test(self, algorytm1,algorytm2):
print('Testuję...')
for (parametr,oczekiwany) in self.parametry:
wynik = algorytm1(parametr)
assert_equal(wynik, oczekiwany)
wynik = algorytm2(parametr)
assert_equal(wynik, oczekiwany)
print('Sukces')
def main():
test = Testowanie()
r1 = Rozwiazanie()
r2 = Rozwiazanie2()
try:
test.test(r1.algorytm,r2.algorytm)
except AttributeError as e:
print e
pass
if __name__ == '__main__':
main()