我正在尝试在Delphi中定义一个常量:
const
FNV_offset_basis = 14695981039346656037;
我得到错误:整数常数太大
注意:
14,695,981,039,346,656,037
十进制等于0x14650FB0739D0383
十六进制。
我如何声明此Int64
常数?
我尝试过的其他一些事情:
const
FNV_offset_basis: Int64 = 14695981039346656037;
FNV_offset_basis = Int64(14695981039346656037);
FNV_offset_basis: Int64 = Int64(14695981039346656037);
var
offset: LARGE_INTEGER;
begin
//recalculate constant every function call
offset.LowPart = $739D0383;
offset.HighPart = $14650FB0;
校正
我的基本假设是错误的。
将14695981039346656037
粘贴到Windows 7计算器中,并转换为十六进制,让我相信14695981039346656037
的十六进制等值为0x14650FB0739D0383
:
这是不正确的。
因此,当我看到16位十六进制值,高位未设置时,我认为它可以适合64位签名整数。
实际上,14695981039346656037
的十六进制等价物是......其他的东西。罗布,你是对的! (可能)
答案 0 :(得分:11)
问题中的十六进制转换不正确。该数字实际上是$ cbf29ce484222000,并且不适合带符号的64位整数。您需要一个无符号的64位整数来表示它。 Delphi 5中没有未签名的UInt64,所以你运气不好。没有可以在您的Delphi版本中表示该数字的整数数据类型。
如果满足您的需要,您可以将位模式解释为带符号值。在这种情况下,你会有一个负数。
答案 1 :(得分:5)
该数字大于有符号的64位整数可以容纳的数字。您是否尝试过使用UInt64
?
答案 2 :(得分:5)
我只需要64位变量来保存64位(无符号)数字。我仍然可以使用Delphi的Int64
来完成它,但诀窍是如何声明我需要的常量:
const
FNV_offset_basis: ULARGE_INTEGER = (LowPart: $cbf29ce4; HighPart: $84222000);
(感谢Dave和Rob找到正确的十六进制值)
虽然我是,严格来说,不使用Int64
,我正在使用Int64:
var
hash: Int64;
begin
hash := FNV_offset_basis.QuadPart;
for i := 1 to Length(s) do
begin
hash := hash xor Byte(s[i]);
hash := UInt64Mul(hash, 1099511628211);
end;
Result := UInt64mod(hash, map.Length);
end;
使用一些精心设计的UInt64Xxx
数学例程:
function UInt64mod(const Dividend: Int64; const Divisor: DWORD): DWORD;
var
d2: LongWord;
remainder: LongWord;
begin
//Upper half of dividend cannot be larger than divisior, or else a #de divide error occurs
//Keep multiplying by two until it's larger.
//We fixup at the end
d2 := Divisor;
while d2 < u.HighPart do
d2 := d2 * 2;
asm
MOV EDX, ULARGE_INTEGER(Dividend).HighPart;
MOV EAX, ULARGE_INTEGER(Dividend).LowPart;
MOV ECX, d2;
//EAX := EDX:EAX / r/m32, EDX=remainder
DIV ECX;
MOV remainder,EDX
end;
//Fixup for using larger divisor
Result := remainder mod Divisor;
end;
我会将实施UInt64Mul
作为读者的练习。
答案 3 :(得分:0)
我有一个WMI调用返回了Delphi 5不支持的Uint64类型的Variant。 通过假设Int64对我期望的结果足够公平, 1- I Typecasted并将返回的Variant存储到扩展(Real Type)中, 2-我使用了“Trunc”函数,在需要时从Extended返回Int64。
不完全是你想要的,但考虑真实类型可能会帮助某人实现一些“不可能”的Delphi 5数学。
答案 4 :(得分:-1)
Windows 7计算器出现故障并在没有警告的情况下剥离最后一个数字,即使选择了QWord,计算器也似乎无法真正计算出64位数。它似乎只是在Windows 7中的Int64计算器,它也无法显示足够的数字并简单地将它们剥离为完全错误的值。有趣的是,Windows XP计算器没有此Bug。
真正的十六进制值14695981039346656037是0xCBF29CE484222325也14695981039346656037 =(20921 * 465383 * 1509404459)现在作为证明尝试用这个计算器计算它你将得到-3750763034362895579(签名)而不是程序员中的14695981039346656037(无符号)模式,但在科学模式下是正确的。