Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 如何快速将数字字符数组转换为整数?_Delphi_Performance - Fatal编程技术网

Delphi 如何快速将数字字符数组转换为整数?

Delphi 如何快速将数字字符数组转换为整数?,delphi,performance,Delphi,Performance,情况:在字节数组(TBytes)中保存为十六进制的整数。如果可能的话,在不进行任何复制的情况下,将该数字转换为整数类型,并减少复制次数 下面是一个例子: array = ($35, $36, $37); 这是ansi中的“5”、“6”、“7”。如何将其转换为567($273)而麻烦更少 我抄了两遍。有可能做得更快吗?怎么做 function BytesToInt(const bytes: TBytes): integer; var i: integer; begin result :=

情况:在字节数组(TBytes)中保存为十六进制的整数。如果可能的话,在不进行任何复制的情况下,将该数字转换为整数类型,并减少复制次数

下面是一个例子:

array = ($35, $36, $37);
这是ansi中的“5”、“6”、“7”。如何将其转换为567($273)而麻烦更少

我抄了两遍。有可能做得更快吗?怎么做

function BytesToInt(const bytes: TBytes): integer;
var
  i: integer;
begin
  result := 0;
  for i := 0 to high(bytes) do
    result := (result shl 4) + HexToInt(bytes[i]);
end;

正如PA指出的,这当然会溢出足够的数字。HexToInt的实现和错误处理一样留给读者作为练习。

您可以使用查找表来代替HexToInt

此过程仅适用于AnsiChars,当然不提供错误检查

var
  Table        :array[byte]of byte;

procedure InitLookupTable;
var
  n:            integer;
begin
  for n := 0 to Length(Table) do
    case n of
      ord('0')..ord('9'): Table[n] := n - ord('0');
      ord('A')..ord('F'): Table[n] := n - ord('A') + 10;
      ord('a')..ord('f'): Table[n] := n - ord('a') + 10;
    else Table[n] := 0;
    end;
end;

function HexToInt(var hex: TBytes): integer;
var
  n:            integer;
begin
  result := 0;
  for n := 0 to Length(hex) -1 do
    result := result shl 4 + Table[ord(hex[n])];
end;
你能行

function CharArrToInteger(const Arr: TBytes): integer;
var
  s: AnsiString;
begin
  SetLength(s, length(Arr));
  Move(Arr[0], s[1], length(s));
  result := StrToInt(s);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  a: TBytes;
begin
  a := TBytes.Create($35, $36, $37);
  Caption := IntToStr(CharArrToInteger(a));
end;
如果您知道字符串以null结尾,也就是说,如果数组中的最后一个字符是0,那么您只需执行以下操作即可

function CharArrToInteger(const Arr: TBytes): integer;
begin
  result := StrToInt(PAnsiChar(@Arr[0]));
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  a: TBytes;
begin
  a := TBytes.Create($35, $36, $37, 0);
  Caption := IntToStr(CharArrToInteger(a));
end;
然而,最自然的方法是使用字符数组而不是字节数组!然后编译器可以为您提供一些技巧:

procedure TForm1.FormCreate(Sender: TObject);
var
  a: TCharArray;
begin
  a := TCharArray.Create(#$35, #$36, #$37);
  Caption := IntToStr(StrToInt(string(a)));
end;

不能再快了;-)


如果你发布你的代码,那么我们可以看看如何改进它。十六进制字符串的最大长度是多少?没有限制,它将溢出任何大小的整数“另存为十六进制”是什么意思?请发布一些代码。那个十六进制是从哪里来的,为什么你认为它是十六进制
t字节
不太可能是存储十六进制的数据类型,
String
AnsiString
更可能是因为十六进制只不过是二进制数据的文本表示形式,使用base-16表示法。您的示例与您的文本不匹配。该数组不包含“保存为十六进制的数字”。它包含表示十进制值567的字符,当用十六进制写入时,十进制值为273。您会感到困惑,因为这三个字符的值是用十六进制表示法在代码中编写的,但这三个字节的数值与表示法无关。你可以写
$36
54
Ord('6')
,它们都会给你同样的东西。好吧,这里有一个例子:array=($35,$36,$37);。这是ansi中的“5”、“6”、“7”。如何将其转换为567($273)而麻烦更少?我尝试了您的实现,但它没有做到这一点。这很合理,我解释不清楚。你能帮我吗?它的数量永远不会超过一个单词的大小,但我可以很容易地进行检查。问题是要尽可能快地执行上面的操作。这是我一开始做的。我在第三个答案中找到了解决方案,但由于某种原因被删除了:(但谢谢你!在以内存换取速度的传统交易中,查找表会更快。但我认为你的解决方案是正确的,这才是最重要的。moz是正确的,查找表和由两个字符展开的循环会更快。使用HexToInt(num:PByteArray;size:cardinal)生成的代码也会更快因为绝对技巧将num传递到堆栈,而直接PByteArray将把它留在寄存器中,num^[i]将使用快速lea访问。有关使用查找表的更快的十六进制到二进制例程,请参阅
function HexToInt(num:pointer; size:Cardinal): UInt64;
var i: integer;
    inp: Cardinal absolute num;
begin
  if(size > SizeOf(Result)) then Exit;
  result := 0;
  for i := 0 to size-1 do begin
    result := result shl 4;
    case(PByte(inp+i)^) of
      ord('0')..ord('9'): Inc(Result, PByte(inp+i)^ - ord('0'));
      ord('A')..ord('F'): Inc(Result, PByte(inp+i)^ - ord('A') + 10);
      ord('a')..ord('f'): Inc(Result, PByte(inp+i)^ - ord('a') + 10);
    end;
  end;
end;
function fHexToInt(b:TBytes): UInt64; inline;
begin
  Result:=HexToInt(@b[0], Length(b));
end;

...
b:TBytes = ($35, $36, $37);
HexToInt(@b[0], 3);
fHexToInt(b);