Years ago I needed to test in one of my Delphi software packages if the ID that is typed is accurate. Now I want to document my function to validate the ID. And the software in question tested thousands of ID's, and look to work.
Firstly the South African ID is made up the in following way.
Format: {YYMMDD}{G}{SSS}{C}{A}{Z}
YYMMDD : Date of birth.
G : Gender. 0-4 Female; 5-9 Male.
SSS : Sequence No. for DOB/G combination.
C : Citizenship. 0 SA; 1 Other.
A : Usually 8, or 9 [can be other values]
Z : Control digit calculated in the following section
The formula is as follows to calculate the check digit. I will use the example ID of my source website. 800101 5009 087
1. Add all the digits in the odd positions (excluding last digit).
8 + 0 + 0 + 5 + 0 + 0 = 13
2. Move the even positions into a field and multiply the number by 2.
011098 x 2 = 22196
3. Add the digits of the result in #2.
2 + 2 + 1 + 9 + 6 = 20
4. Add the answer in #1 to the answer in #3.
13 + 20 = 33
5. Subtract the second digit in #4 from 10.
10 - 3 = 7
6. If #5 comes out as 10 you must use 0.
Now for the Delphi function to validate the ID.
Firstly the loop to add all the odd positions.
i := 1;
oddValue := 0;
while i < 13 do
begin
oddValue := oddValue + StrtoInt(copy(ID,i,1));
i := i + 2;
end;
Then the loop to move the even positions into an field.
i := 2;
evenString := '';
while i < 13 do
begin
evenString := evenString + copy(ID,i,1);
i := i + 2;
end;
Multiply the even positions loop value by 2.
evenString := InttoStr(StrtoInt(evenString) * 2);
Now we need to add each of the characters of the even answer.
evenValue := 0;
for i := 1 to Length(evenString) do
begin
evenValue := evenValue + StrtoInt(copy(evenString,i,1));
end;
Add the odd answer and the even answer together.
i := oddValue + evenValue;
Subtract second digit from answer from 10.
CheckDigit := 10 - strtoint(copy(InttoStr(i),2,1));
If answer is 10 use zero.
If CheckDigit > 9 then
CheckDigit := 0;
Finally check if the check digit is the same.
If copy(ID,13,1) <> InttoStr(CheckDigit) then
ValidateIDNEW := False;
Now here is the function all together.
Link to the test project code written in Lazarus at GitHub. The original old function was written in Delphi. With my own projects I am starting to convert from Delphi to Lazarus.
function TMainForm.ValidateIDNEW(ID: String): Boolean;
var
oddValue, evenValue, i, CheckDigit: Integer;
evenString: String;
begin
ValidateIDNEW := True;
If Length(ID) = 13 then
begin
try
i := 1;
oddValue := 0;
while i < 13 do
begin
// 1. Add all the digits in the odd positions (excluding last digit).
oddValue := oddValue + StrtoInt(copy(ID,i,1));
i := i + 2;
end;
i := 2;
evenString := '';
while i < 13 do
begin
// 2. Move the even positions into a field and multiply the number by 2.
evenString := evenString + copy(ID,i,1);
i := i + 2;
end;
evenString := InttoStr(StrtoInt(evenString) * 2);
evenValue := 0;
for i := 1 to Length(evenString) do
begin
// 3. Add the digits of the result in 2.
evenValue := evenValue + StrtoInt(copy(evenString,i,1));
end;
// 4. Add the answer in 1. to the answer in 3.
i := oddValue + evenValue;
// 5. Subtract the second digit in 4. from 10.
CheckDigit := 10 - strtoint(copy(InttoStr(i),2,1));
If CheckDigit > 9 then
CheckDigit := 0;
If copy(ID,13,1) <> InttoStr(CheckDigit) then
ValidateIDNEW := False;
except
ValidateIDNEW := False;
end;
end
else
ValidateIDNEW := False;
end;
And if you wondered why I called the function new I tidied it up a bit. The function below was written long time ago when I just started, and the original version had no loops in it.
function TMainForm.ValidateID(ID: String): Boolean;
var
i1, i2, i3, i4, i5: Integer;
s: String;
begin
ValidateID := True;
If Length(ID) = 13 then
begin
try
i1 := StrtoInt(copy(ID,1,1)) + StrtoInt(copy(ID,3,1)) + StrtoInt(copy(ID,5,1)) + StrtoInt(copy(ID,7,1)) + StrtoInt(copy(ID,9,1)) + StrtoInt(copy(ID,11,1));
i2 := StrtoInt(copy(ID,2,1) + copy(ID,4,1) + copy(ID,6,1) + copy(ID,8,1) + copy(ID,10,1) + copy(ID,12,1)) * 2;
If Length(InttoStr(i2)) = 5 then
s := '0' + InttoStr(i2)
else
begin
If Length(InttoStr(i2)) = 4 then
s := '00' + InttoStr(i2)
else
begin
If Length(InttoStr(i2)) = 3 then
s := '000' + InttoStr(i2)
else
s := InttoStr(i2);
end;
end;
If Length(s) = 6 then
i3 := StrtoInt(copy(s,1,1)) + StrtoInt(copy(s,2,1)) + StrtoInt(copy(s,3,1)) + StrtoInt(copy(s,4,1)) + StrtoInt(copy(s,5,1)) + StrtoInt(copy(s,6,1))
else
i3 := StrtoInt(copy(s,1,1)) + StrtoInt(copy(s,2,1)) + StrtoInt(copy(s,3,1)) + StrtoInt(copy(s,4,1)) + StrtoInt(copy(s,5,1)) + StrtoInt(copy(s,6,1)) + StrtoInt(copy(s,7,1));
i4 := i1 + i3;
i5 := 10 - strtoint(copy(InttoStr(i4),2,1));
If i5 > 9 then
i5 := 0;
If copy(ID,13,1) <> InttoStr(i5) then
ValidateID := False;
except
ValidateID := False;
end;
end
else
ValidateID := False;
end;
Source: http://geekswithblogs.net/willemf/archive/2005/10/30/58561.aspx