我想将大的64位值从十进制或十六进制字符串转换为64位UINT64数据类型。有一个UIntToStr可以帮助将UINT64转换为字符串,但没有办法将64位整数转换为无符号值,作为字符串。这意味着使用RTL不能用十进制或十六进制表示大于2 ** 63的整数值。这通常不是什么大问题,但可能发生用户需要输入一个值,作为无符号整数,必须作为64位无符号整数值存储到注册表中。
procedure HandleLargeHexValue;
var
x:UINT64;
begin
x := $FFFFFFFFFFFFFFFE;
try
x := StrToInt('$FFFFFFFFFFFFFFFF'); // range error.
except
x := $FFFFFFFFFFFFFFFD;
end;
Caption := UintToStr(x);
end;
更新 Val现在在Delphi XE4及更高版本中正常运行。在XE3及以下Val('$ FFFFFFFFFFFFFFFF')有效,但不是Val('9223372036854775899')。正如Roeland在Quality Central 108740中指出的那样:在Delphi XE4之前,System.Val在十进制中出现了大的UInt64值问题。
答案 0 :(得分:6)
更新:在XE4及更高版本中修复了RTL错误。此hack仅在Delphi XE3或更早版本中使用
好吧,如果不存在,我想我总能写出来。
(我为此写了一个非常好的单元测试,但它太大了,不能在这里发布)
unit UIntUtils;
{ A missing RTL function written by Warren Postma. }
interface
function TryStrToUINT64(StrValue:String; var uValue:UInt64 ):Boolean;
function StrToUINT64(Value:String):UInt64;
implementation
uses SysUtils,Character;
{$R-}
function TryStrToUINT64(StrValue:String; var uValue:UInt64 ):Boolean;
var
Start,Base,Digit:Integer;
n:Integer;
Nextvalue:UInt64;
begin
result := false;
Base := 10;
Start := 1;
StrValue := Trim(UpperCase(StrValue));
if StrValue='' then
exit;
if StrValue[1]='-' then
exit;
if StrValue[1]='$' then
begin
Base := 16;
Start := 2;
if Length(StrValue)>17 then // $+16 hex digits = max hex length.
exit;
end;
uValue := 0;
for n := Start to Length(StrValue) do
begin
if Character.IsDigit(StrValue[n]) then
Digit := Ord(StrValue[n])-Ord('0')
else if (Base=16) and (StrValue[n] >= 'A') and (StrValue[n] <= 'F') then
Digit := (Ord(StrValue[n])-Ord('A'))+10
else
exit;// invalid digit.
Nextvalue := (uValue*base)+digit;
if (Nextvalue<uValue) then
exit;
uValue := Nextvalue;
end;
result := true; // success.
end;
function StrToUINT64(Value:String):UInt64;
begin
if not TryStrToUINT64(Value,result) then
raise EConvertError.Create('Invalid uint64 value');
end;
end.
答案 1 :(得分:4)
我必须不同意Val解决了这个问题。 当用Hex编写时,Val仅适用于大的UInt64值。当它们以十进制形式写入时,最后一个字符将从字符串中删除,结果值是错误的。
参见Quality Central 108740: System.Val has problems with big UInt64 values 编辑:似乎这个问题应该在XE4中解决。无法测试。
答案 2 :(得分:3)
使用Value a UINT64,下面的代码片段给出了Delphi 2010的预期答案,但前提是输入值是十六进制
stringValue := '$FFFFFFFFFFFFFFFF';
val( stringValue, value, code );
ShowMessage( UIntToStr( value ));
我只是简单地将val包装在一个便利功能中,你就完成了。
现在随时烧我。我在测试中错过了一个数字吗? :d