【问题标题】:How to declare an Int64 constant?如何声明一个 Int64 常量?
【发布时间】:2012-04-24 17:26:09
【问题描述】:

我正在尝试在 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 位 有符号整数。 p>

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

【问题讨论】:

  • 你试过了吗:FNV_offset_basis = $14650FB0739D0383;
  • 备案:“FNV_offset_basis = 14695981039346656037”适用于 Delphi XE2。
  • @RRUZ 这个问题是关于 unsigned 64 位整数的。这是关于 Delphi 及其 signed 64 位整数的。该线程中的一个聪明的答案是“购买新版本的 Delphi”(谢谢
  • @RobKennedy 也删除了我的 :)

标签: delphi constants delphi-7 delphi-5 int64


【解决方案1】:

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

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

【讨论】:

  • 数字已签名,并且适合,已签名,放入 Int64。
  • 不合适。它是 cbf29ce484222000
  • 你是对的。从根本上说,我只需要将 64 位存储在一个 64 位变量中足够长的时间,以便对其执行 mod 操作(但从根本上说)。假设$cbf29ce484222000 是一个有符号 64 位整数,它的十进制值是多少?
  • -$340D631B7BDDE000 或 -3750763034362896384
  • 这个答案有问题吗?还是乔恩的?
【解决方案2】:

这个数字比一个有符号的 64 位整数要大。您是否尝试过改用UInt64

【讨论】:

  • Delphi 5 (1999) 和 7 (2002) 都有Int64,但都没有UInt64。但是,现代 Delphi 版本可以。 :)
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

      和14695981039346656037真正的十六进制值是0xCBF29CE484222325也14695981039346656037 =(20921 * 465383 * 1509404459)现在作为证据尝试使用这个计算器计算的话,你会在程序员得到-3750763034362895579(签字)而不是14695981039346656037(无符号)模式,但在科学模式下会正确。

      【讨论】:

      • @Amenom 您应该努力合并您的帐户。请使用contact form
      猜你喜欢
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 2012-10-19
      相关资源
      最近更新 更多