Solved

How to make a checksum procedure?

Posted on 2001-06-21
17
203 Views
Last Modified: 2010-04-06
Hi guys,

I need to make a checksum procedure. Can someone help me?

I have a 15 digit number:

Num:=220840001229500

The last 2 digits are zeroes by default.
To get a "control number" I have to perform the following calculation:

I divide Num with 97, thats:

220840001229500:97=2276701043603.09xxxx

Now I have to use the second digit of this result - the 9.

(97+1)-9=89

So 89 is my "control number",
and now at the end, Num: the last 2 zeroes get replaced with the "control number" and Num2: would be

Num2:=2208400012295/89

Greetings, Blash
0
Comment
Question by:blash
  • 8
  • 8
17 Comments
 
LVL 5

Expert Comment

by:TheNeil
ID: 6213487
Try this:

Num := 220840001229500;
rTemp := Num / 97;
iDigit := TRUNC(ABS(FRAC(rTemp)) * 100) DIV 10;
iDigit := (97 + 1) - iDigit;
Num2 := (Num DIV 100) * 100 + iDigit;

You will need to declare Num and Num2 as Int64 variables (Longint ain't big enough)

The Neil =:)
0
 

Author Comment

by:blash
ID: 6213607
Dear Neil,

What if my Num: is a DBEdit7.Text?
And how do I declare an Int64

Blash

0
 
LVL 3

Expert Comment

by:f15iaf
ID: 6213627
add to the neil code:
var
       num,num2,idigit:int64;
       rtemp:extended;
begin

Num :=  strtoint(DBEdit7.Text);{220840001229500}
rTemp := Num / 97;
iDigit := TRUNC(ABS(FRAC(rTemp)) * 100) DIV 10;
iDigit := (97 + 1) - iDigit;
Num2 := (Num DIV 100) * 100 + iDigit;
end;
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 6213735
Exactly as f15iaf says although personally I'd check the StrToInt conversion:

TRY
  Num := StrToInt(DBEdit7.Text);
EXCEPT
  //Do something useful
END;

The Neil =:)
0
 

Author Comment

by:blash
ID: 6213841
The code works,

but I get a Error message:

EConvertError with message "220401000207585" is not a valid integer value.

Why?
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 6214127
Ahhh. IntToStr can't handle the size of the value. What you need to do is either write your own routine to do it or use this one


  FUNCTION BigStrToInt(sValue : STRING): INT64;
  VAR
    iCount : LONGINT;
  BEGIN
    Result := 0;
    FOR iCount := 1 TO Length(sValue)
    DO
      Result := Result * 10 + StrToInt(sValue[iCount]);
  END;

It then just gets called in the same way as IntToStr:

VAR
  iNum : INT64;
begin
  iNum := BigStrToInt('220401000207585');
...

The Neil =:)
0
 

Author Comment

by:blash
ID: 6223662
Dear The Neil,

I think that your BigStrToInt function works.

But now I get another Error message after running the code block. I get:
EAccessViolation at address...Read of address FFFFFFFF.

I am appending the code now. Can you see something wrong there?

procedure TForm1.Table2BeforePost(DataSet: TDataSet);
var
  Num, Num2, idigit: int64;
  rtemp: extended;
//Od The Neil
  iNum: int64;
//
begin
//moe,ama samo dopola vrsi rabota
//  if Pos('4',DBEdit7.Text)>0 then
  if Copy(DBEdit7.Text,1,1) = '4' then  //Od Mohhamed
  begin
   ShowMessage('Value must not start with a 4');
   Table2.Cancel;
  end;
//Od Neil
iNum:=BigStrToInt(DBEdit7.Text);
rTemp:=iNum/97;
iDigit:=TRUNC(ABS(FRAC(rTemp))*100)DIV 10;
iDigit:=(97+1)-iDigit;
Num2:=(iNum DIV 100)*100+iDigit;
//Od Neil
  if iDigit<>89 then
  begin
   ShowMessage('the bank account is not correct');
   Table2.Cancel;
  end;
end;
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 6224792
Well it depends on which values you're putting into it that are causing the error (the access voliation itself means nothing). I did spot one thing though (but I don't think it's the problem), try adding a Exit to the first IF statement:

 if Copy(DBEdit7.Text,1,1) = '4' then  //Od Mohhamed
 begin
  ShowMessage('Value must not start with a 4');
  Table2.Cancel;
  Exit;
 end;

Beyond that then it's a case of looking at the data. Can you post a value (or values) that are causing problems?

The Neil =:)
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:blash
ID: 6226637
Dear The Neil,

After cheking out my question, I saw that I must redefine it. I'll do that later during the day. I'll try that "Exit;" anyway. Thanks for helping me.

Greetings, Blash
0
 

Author Comment

by:blash
ID: 6227653
Hi The Neil,

The 15 digit number is:

Num:=220840001229500

The last 2 digits are not zeroes by default.
To get the "control number" I have to perform the following calculation:

I  divide Num with 97, but I need the reminder, that's:

220840001229500 mod 97, so the reminder is 9.

So now I need this reminder "9" for the "control number":

(97+1)-"reminder"=(97+1)-9=89

So now my Num2: is:

2208400012295/89

If the "reminder" would be "0" then by default the "control number" would be "89".

I hope I got it right now.

Thanks, Blash
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 6234252
Well using the steps you've mentioned the code below will do what you want. I've included loads of comments so hopefully if there is a problem with the approach then we should be able to spot it:

procedure TForm1.Button1Click(Sender: TObject);

 FUNCTION BigStrToInt(sValue : STRING): INT64;
 VAR
   iCount : LONGINT;
 BEGIN
   Result := 0;
   FOR iCount := 1 TO Length(sValue)
   DO
     Result := Result * 10 + StrToInt(sValue[iCount]);
 END;

VAR
  iValue  : INT64;
  iResult : INT64;
  sValue  : STRING;
begin
  sValue := '220840001229500';
  //Get the stribg into an integer
  iValue  := BigStrToInt(sValue);
  //We're only interested in the final two digits for calculating the checksum
  //BUT we need remember the rest of the value (minus the last two digits) so
  //strip off the last two digitd by dividing by 100
  iResult := iValue DIV 100;
  //Divide the COMPLETE value by 97
  iValue  := iValue MOD 97;
  //Calculate the checksum
  iValue  := (97 + 1) - iValue;

  //Add the two checksum digits to the end of the value
  //iResult is the original number but with the last two digits stripped. If we
  //add on two extra zeroes (by multiplying by 100), we can then add the
  //checksum value straight onto the end to give us a final value
  iResult := iResult * 100 + iValue;

  ShowMessage('Result: ' + IntToStr(iResult));
end;

The Neil =:)
0
 

Author Comment

by:blash
ID: 6237315
Dear The Neil :)))

The code works prefectly, only one thing:

How can I say in code at the place where:

sValue:='220840001229500';

take care only for the first 13 digits,leave the 14th and 15th alone (thats taken care later with:

iResult:=iResult*100+iValue;

Thanks Blash ;)))

0
 
LVL 5

Expert Comment

by:TheNeil
ID: 6239475
I'm not sure what you mean. As it stands, the code strips off the last two digits (14th and 15th) works out the checksum and then adds the two new values onto the end when it's finished (so you end up with the same number of digits). It's effectively ignoring the 14th and 15th digits and only basing it's calculation on the first 13

The Neil =:(
0
 

Author Comment

by:blash
ID: 6243984
Dear The Neil :)))

So sorry that I'm nagging you with my stupid question. You have more then deserved my pityful 50 points. Have you had a nice weekend? I hope this would be the last that you hear from me - concerning this question.

Your code works perfectly for me if I, for example, have this number:
220401000207682, but only if I enter it as:
220401000207600.

In fact I need, after running your procedure that:
sValue: would be the same as iResult:

I hope I've explained it now.

Sincerely, Blash
0
 
LVL 5

Accepted Solution

by:
TheNeil earned 50 total points
ID: 6249434
I think I understand now - You want to totally ignore the final two digits when the value is being processed and simply replace them at the very end of the calculation (ie you could have the last two dogots as any value and they won't affect the checksum as it's based on the rest of the value).

What you need then is this:

procedure TForm1.Button1Click(Sender: TObject);

  FUNCTION BigStrToInt(sValue : STRING): INT64;
  VAR
    iCount : LONGINT;
  BEGIN
    Result := 0;
    FOR iCount := 1 TO Length(sValue)
    DO
      Result := Result * 10 + StrToInt(sValue[iCount]);
  END;

VAR
 iValue  : INT64;
 iResult : INT64;
 sValue  : STRING;
begin
 sValue := '220401000207682';
 //Get the stribg into an integer
 iValue  := BigStrToInt(sValue);
 //We're only interested in the final two digits for calculating the checksum
 //BUT we need remember the rest of the value (minus the last two digits) so
 //strip off the last two digitd by dividing by 100
 iResult := iValue DIV 100;
 //Divide the COMPLETE value by 97
 iValue  := ((iValue DIV 100) * 100) MOD 97;
 //Calculate the checksum
 iValue  := (97 + 1) - iValue;

 //Add the two checksum digits to the end of the value
 //iResult is the original number but with the last two digits stripped. If we
 //add on two extra zeroes (by multiplying by 100), we can then add the
 //checksum value straight onto the end to give us a final value
 iResult := iResult * 100 + iValue;

 ShowMessage('Result: ' + IntToStr(iResult));
end;

Although it looks to be just about the same code, it's now replacing the final two dogits with zeroes BEFORE doing the checksum calculation. After it's done the calculation it then just replaces the final two dogots with the checksum value. Hope that's what you needed

The Neil =:)
0
 

Author Comment

by:blash
ID: 6251699
That was perfect.
Thank you The Neil.
Hope we'll meet again on EE.

Blash :)))
0
 
LVL 5

Expert Comment

by:TheNeil
ID: 6251892
Anytime

The Neil =:)
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.

914 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now