firemonkey android crc16 结果与 windows 的 delphi 不匹配

firemonkey android crc16 result mismatch with delphi for windows

在两个不同的项目中,我需要在 windows 中使用 crc16 checksum.one,而在 android.i 中的其他项目使用了 windows 的代码,并且效果很好。

showmessage(  bin2crc16(HexToBin('1234'))    );   //---> 0EC9

这里是winsows用到的函数

function Pow(i, k: Integer): Integer;
var
  j, Count: Integer;
begin
  if k>0 then j:=2
    else j:=1;
  for Count:=1 to k-1 do
    j:=j*2;
  Result:=j;
end;

function BinToDec(Str: string): Integer;
var
  Len, Res, i: Integer;
  Error: Boolean;
begin
  Error:=False;
  Len:=Length(Str);
  Res:=0;
  for i:=1 to Len do
    if (Str[i]='0')or(Str[i]='1') then
      Res:=Res+Pow(2, Len-i)*StrToInt(Str[i])
    else
    begin
      //MessageDlg('It is not a binary number', mtInformation, [mbOK], 0);
      Error:=True;
      Break;
    end;
  if Error=True then Result:=0
    else Result:=Res;
end;
//------------------------------------------------------------------------------
function CRC16CCITT(bytes: array of Byte): Word;
const
  polynomial = 21;
var
  crc: Word;
  I, J: Integer;
  b: Byte;
  bit, c15: Boolean;
begin
  crc := $FFFF;
  for I := 0 to High(bytes) do
  begin
    b := bytes[I];
    for J := 0 to 7 do
    begin
      bit := (((b shr (7-J)) and 1) = 1);
      c15 := (((crc shr 15) and 1) = 1);
      crc := crc shl 1;
      if ((c15 xor bit) <> false) then crc := crc xor polynomial;
    end;
  end;
  Result := crc and $ffff;
end;
//------------------------------------------------------------------------------
function HexToDec(const Str: string): Integer;
begin
  if (Str <> '') and ((Str[1] = '-') or (Str[1] = '+')) then
    Result := StrToInt(Str[1] + '$' + Copy(Str, 2, MaxInt))
  else
    Result := StrToInt('$' + Str);
end;
//------------------------------------------------------------------------------
function bin2crc16(str: string): string;
var
I:integer;
lengthCount : integer;
crcByteArr : array of Byte;
crcOut : Word;
begin
  lengthCount := Trunc(length(str)/8);
  setlength(crcByteArr , lengthCount );
  for I := 0 to lengthCount-1 do
  begin
    crcByteArr[I] := BinToDec(copy(str, I*8+1, 8));
  end;
  crcOut := CRC16CCITT(crcByteArr);

  result := crcOut.ToHexString;

end;
//------------------------------------------------------------------------------
function HexToBin(Hexadecimal: string): string;
const
  BCD: array [0..15] of string =
    ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
    '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111');
var
  i: integer;
begin
  Result := '';
  for i := Length(Hexadecimal) downto 1 do
    Result := BCD[StrToInt('$' + Hexadecimal[i])] + Result;
end;

但对于 android,我更改了代码以处理零索引字符串。 结果不同

memo2.Lines.Add( bin2crc16(HexToBin('1234')) ); //-----> 1AFa

这里是android

中用到的函数
function BinToDec(Str: string): Integer;
var
  Len, Res, i: Integer;
  Error: Boolean;
begin
  Error:=False;
  Len:=Length(Str);
  Res:=0;
  for i:=0 to Len-1 do
    if (Str[i]='0')or(Str[i]='1') then
      Res:=Res+Pow(2, Len-i)*StrToInt(Str[i])
    else
    begin
      Error:=True;
      Break;
    end;
  if Error=True then Result:=0
    else Result:=Res;
end;
//------------------------------------------------------------------------------
function CRC16CCITT(bytes: array of Byte): Word;
const
  polynomial = 21;
var
  crc: Word;
  I, J: Integer;
  b: Byte;
  bit, c15: Boolean;
begin
  crc := $FFFF;
  for I := 0 to High(bytes) do
  begin
    b := bytes[I];
    for J := 0 to 7 do
    begin
      bit := (((b shr (7-J)) and 1) = 1);
      c15 := (((crc shr 15) and 1) = 1);
      crc := crc shl 1;
      if ((c15 xor bit) <> false) then crc := crc xor polynomial;
    end;
  end;
  Result := crc and $ffff;
end;
//------------------------------------------------------------------------------
function bin2crc16(str: string): string;
var
I:integer;
lengthCount : integer;
crcByteArr : array of Byte;
crcOut : Word;
begin
  lengthCount := Trunc(length(str)/8);
  setlength(crcByteArr , lengthCount );
  for I := 0 to lengthCount-1 do
  begin
    crcByteArr[I] := BinToDec(copy(str, I*8, 8));
  end;
  crcOut := CRC16CCITT(crcByteArr);

  result := crcOut.ToHexString;

end;
//-----------------------------------------------------------------------------------
function HexToBin(Hexadecimal: string): string;
const
  BCD: array [0..15] of string =
    ('0000', '0001', '0010', '0011', '0100', '0101', '0110', '0111',
    '1000', '1001', '1010', '1011', '1100', '1101', '1110', '1111');
var
  i: integer;
begin
  Result := '';
  for i := Length(Hexadecimal)-1 downto 0 do
    Result := BCD[StrToInt('$' + Hexadecimal[i])] + Result;
end;
//---------------------------------------------------------------------------------
function Pow(i, k: Integer): Integer;
var
  j, Count: Integer;
begin
  if k>0 then j:=2
    else j:=1;
  for Count:=1 to k-1 do
    j:=j*2;
  Result:=j;
end;

我该如何解决我的问题!?

您还没有针对零长度字符串调整 HexToBin 函数。

您的 BinToDec 函数也有问题。您的功率计算是错误的,因为字符串中的索引已更改。可能最简单的处理方法如下,尽管您也可以在 POW 函数中调整索引

function BinToDec(Str: string): Integer;
var
  Len, Res, i: Integer;
  Error: Boolean;
begin
  Error:=False;
  Len:=Length(Str);
  Res:=0;
  for i:=1 to Len do
    if (Str[I - 1]='0')or(Str[I - 1]='1') then
      Res:=Res+Pow(2, Len-i)*StrToInt(Str[I - 1])
    else
    begin
      Error:=True;
      Break;
    end;
  if Error=True then Result:=0
    else Result:=Res;
end;

最后要注意的是 'Copy' 即使在基于零的字符串上也使用基于一的索引,但您假设它是零索引的。我同意这令人困惑,但确实如此。