Delphi 如何快速将数字字符数组转换为整数?
情况:在字节数组(TBytes)中保存为十六进制的整数。如果可能的话,在不进行任何复制的情况下,将该数字转换为整数类型,并减少复制次数 下面是一个例子: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 :=
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);