Delphi - Lenze标准寻址 - 代码转换

时间:2014-03-20 16:01:22

标签: delphi numbers delphi-xe3

来自Lenze manual

Code number (C1, C2)
Standard addressing
The meaning of the code numbers and the assigned parameters can be obtained from
the code table (see chapter 8.2). When transmitting data, the code number are
coded as follows:
The following calculation determines the two ASCII digits from the code number
(value range: 0..6229) (value range: 48dec 127dec):
C1 = INTEGER((REMAINDER(code number/790))/10) + 48dec
C2 = REMAINDER(REMAINDER(code number/790)/10) + 
     INTEGER(code number/790) x 10 + 48dec

从codenumber计算C1和C2的程序。

procedure pCodeNumberToC1C2(CodeNumber: Word; var C1, C2: Byte);
begin
  C1 := Byte((CodeNumber mod 790) div 10) + 48;
  C2 :=     ((CodeNumber mod 790) mod 10) + 48 + 10 * Byte(CodeNumber div 790);
end;

但是,如何在没有这种情况的情况下以另一种方式计算它:

function fC1C2ToCodeNumber(iC1, iC2: Byte): Word;
var
  C1, C2: Byte;
  i: Integer;
Begin
  Result := 0;
  For i := 0 to 6229 Do Begin
    pCodeNumberToC1C2(i, C1, C2);
    if (C1 = iC1) and (C2 = iC2) Then Result := i;
  End;
  Result := cn;
End;

2 个答案:

答案 0 :(得分:3)

Let's 
N = p * 790 + q
then
c1 = 48 + q div 10
c2 = 48 + q mod 10 + 10 * p
so
p = (c2-48) div 10
q = (c2-48) mod 10 + (c1-48) * 10

试验:

var
  c1, c2: Byte;
  n, p, q, t: Word;
begin
  for t := 0 to 6229 do begin
    n := t;
    pCodeNumberToC1C2(n, c1, c2);
    p := (c2-48) div 10;
    q := (c2-48) mod 10 + (c1-48) * 10;
    n := 790*p+q;
    if n <> t then
      Memo1.Lines.Add('Failed at ' + IntToStr(t))
  end;

决赛:

function C1C2ToCodeNumber(C1, C2: Byte): Word;
begin
Result := ((C2 - 48) div 10) * 790 + ((C2 - 48) mod 10 + (C1 - 48) * 10);
end;

答案 1 :(得分:1)

作为算术的替代方法,您可以考虑查找表。以内存为代价,这可以提供更好的性能。代码如下所示:

const
  CodeNumberTable: array [48..126, 48..127] of Word = (
    .... code removed because of Sack Overflow post size limitation
  );

const
  MinC1 = low(CodeNumberTable);
  MinC2 = high(CodeNumberTable);
  MaxC1 = low(CodeNumberTable[MinC1]);
  MaxC2 = high(CodeNumberTable[MinC1]);

type
  EInvalidParameters = class(Exception);

function fC1C2ToCodeNumber(iC1, iC2: Byte): Word;
begin
  if not InRange(iC1, MinC1, MaxC1) then
    raise EInvalidParameters.CreateFmt(
      'iC1 (%d) must be in the range %d to %d',
      [iC1, MinC1, MaxC1]
    );
  if not InRange(iC2, MinC2, MaxC2) then
    raise EInvalidParameters.CreateFmt(
      'iC2 (%d) must be in the range %d to %d',
      [iC2, MinC2, MaxC2]
    );
  Result := CodeNumberTable[iC1, iC2];
  if Result=high(Word) then
    raise EInvalidParameters.CreateFmt(
      'CodeNumber not defined for iC1=%d, ic2=%d',
      [iC1, iC2]
    );
end;

如果您有兴趣,我可以通过粘贴箱提供表格。