5

我正在尝试在 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 Calculator 中,并转换为十六进制,让我相信十六进制等效146959810393466560370x14650FB0739D0383

在此处输入图像描述

这是不正确的。

因此,当我看到一个 16 位十六进制值且高位未设置时,我认为它可以放入 64 位有符号整数。

实际上,十六进制等价物14695981039346656037是……别的东西。罗布,你是对的!(大概)

4

5 回答 5

11

您在问题中的十六进制转换不正确。该数字实际上是 $cbf29ce484222000 并且不适合有符号的 64 位整数。您需要一个无符号的 64 位整数来表示它。Delphi 5 中没有未签名的 UInt64,所以你不走运。在您的 Delphi 版本中,没有可以表示该数字的整数数据类型。

如果您需要的话,您也许可以将位模式解释为有符号值。在这种情况下,您将有一个负数。

于 2012-04-24T17:36:37.410 回答
5

我只需要 64 位变量来保存 64 位(无符号)数字。我仍然可以使用 DelphiInt64来完成它,但诀窍是如何声明我需要的常量:

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作为练习留给读者。

于 2012-04-24T20:23:09.660 回答
5

该数字大于带符号的 64 位整数可以容纳的数量。您是否尝试过使用UInt64

于 2012-04-24T17:30:45.787 回答
0

我有一个 WMI 调用,它返回了 Delphi 5 不支持的 Uint64 类型的 Variant。假设 Int64 对我期望的结果足够公平,1-我对返回的 Variant 进行类型转换并将其存储到扩展(真实类型)中,2 - 我使用了“Trunc”函数,它在需要时从 Extended 返回 Int64。

不完全是您想要的,但考虑 Real Types 可能会帮助某人实现一些“不可能”的 Delphi 5 数学。

于 2015-12-01T20:36:01.797 回答
-1

Windows 7 计算器出现故障并在没有警告的情况下删除最后一个数字,即使选择了 QWord,计算器似乎也无法真正以 64 位计算。它似乎是仅在 Windows 7 中的 Int64 计算器,它也无法显示足够的数字,并且只是将它们剥离为完全错误的值。有趣的是,Windows XP 计算器没有这个错误。

And the real Hex Value of 14695981039346656037 is 0xCBF29CE484222325 also 14695981039346656037 = (20921 * 465383 * 1509404459) now as a proof try to calculate it with this Calculator and you will get -3750763034362895579 (signed) instead of 14695981039346656037 (unsigned) in Programmer Mode, but在科学模式下它将是正确的。

于 2015-04-14T23:18:44.960 回答