简体   繁体   English

如何声明Int64常量?

[英]How to declare an Int64 constant?

i'm trying to define a constant in Delphi: 我试图在Delphi中定义一个常量:

const
   FNV_offset_basis = 14695981039346656037;

And i get the error: Integer constant too large 我得到错误: 整数常数太大

Note: 14,695,981,039,346,656,037 decimal is equal to 0x14650FB0739D0383 hex. 注意: 14,695,981,039,346,656,037十进制等于0x14650FB0739D0383十六进制。

How can i declare this Int64 constant? 我如何声明这个Int64常量?

Some other things i've tried: 我尝试过的其他一些事情:

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;

Correction 更正

My fundamental assumption was wrong. 我的基本假设是错误的。

Pasting 14695981039346656037 into Windows 7 Calculator, and converting to hex, led me to believe that the hex equivalent of 14695981039346656037 is 0x14650FB0739D0383 : 14695981039346656037粘贴到Windows 7计算器,并转换为十六进制,让我相信14695981039346656037的十六进制等效146959810393466560370x14650FB0739D0383

在此输入图像描述

That is incorrect. 那是不对的。

So when i saw a 16-digit hex value, with the high bit not set , i presumed it could fit in a 64-bit signed integer. 因此,当我看到一个16位十六进制值, 未设置高位时,我认为它可以适合64位有符号整数。

In reality the hex equivalent of 14695981039346656037 is...something else. 实际上,十六进制当量为14695981039346656037是......其他的东西。 Rob, you were right! 罗布,你是对的! (probably) (大概)

Your hex conversion in the question is incorrect. 您在问题中的十六进制转换不正确。 That number is actually $cbf29ce484222000 and does not fit into a signed 64 bit integer. 该数字实际上是$ cbf29ce484222000,并且不适合带符号的64位整数。 You would need an unsigned 64 bit integer to represent it. 您需要一个无符号的64位整数来表示它。 There is no unsigned UInt64 in Delphi 5 and so you are out of luck. Delphi 5中没有未签名的UInt64,所以你运气不好。 There is no integral data type that can represent that number in your version of Delphi. 没有可以在您的Delphi版本中表示该数字的整数数据类型。

You could perhaps interpret the bit pattern as a signed value if that does what you need. 如果满足您的需要,您可以将位模式解释为带符号值。 In that case you would have a negative number. 在这种情况下,你会有一个负数。

That number is bigger than a signed 64-bit integer can hold. 该数字大于有符号的64位整数可以容纳的数字。 Have you tried using UInt64 instead? 您是否尝试过使用UInt64

i only needed the 64-bit variable to hold a 64-bit (unsigned) number. 我只需要64位变量来保存64位(无符号)数字。 i can still use Delphi's Int64 to accomplish it, but the trick was how to declare my needed constants: 我仍然可以使用Delphi的Int64来完成它,但诀窍是如何声明我需要的常量:

const
    FNV_offset_basis: ULARGE_INTEGER = (LowPart: $cbf29ce4; HighPart: $84222000);

(thanks for Dave and Rob for finding me the correct hex value) (感谢Dave和Rob找到正确的十六进制值)

While i am, strictly speaking, not using the Int64 , i am using an Int64: 虽然我是严格来说,不使用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;

With some carefully crafted UInt64Xxx math routines: 使用一些精心设计的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;

i'll leave the implementation UInt64Mul as an exercise for the reader. 我将把实现UInt64Mul留给读者练习。

I had a WMI call that returned a Variant of type Uint64 not supported by Delphi 5. By assuming that Int64 was fair enough for the result I was expecting, 1- I Typecasted and stored the returned Variant into an Extended (Real Type), 2- I used the "Trunc" function that returns an Int64 from an Extended when needed. 我有一个WMI调用返回了Delphi 5不支持的Uint64类型的Variant。通过假设Int64对我期望的结果足够公平,1- I Typecasted并将返回的Variant存储到扩展(Real Type),2 - 我使用了“Trunc”函数,在需要时从Extended返回Int64。

Not exactly what you want but considering Real Types might help someone to achieve some "impossible" Delphi 5 math. 不完全是你想要的,但考虑真实类型可能会帮助某人实现一些“不可能”的Delphi 5数学。

The Windows 7 Calculator is faulty and strips the last Digit without warning also the Calculator seems not able to really calculate in 64Bits even if QWord is selected. Windows 7计算器出现故障,并且在没有警告的情况下剥离最后一个数字,即使选择了QWord,计算器也似乎无法真正计算64位。 It seems to be a Int64 Calculator only in Windows 7 and it also can't display enough Digits and simply strips them to a totally wrong Value. 它似乎只是在Windows 7中的Int64计算器,它也无法显示足够的数字,只是将它们剥离为完全错误的值。 Interestingly the Windows XP Calculator does not have this Bug. 有趣的是,Windows XP计算器没有此Bug。

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 it will be correct in Scientific Mode. 14695981039346656037的实际十六进制值是0xCBF29CE484222325也是14695981039346656037 =(20921 * 465383 * 1509404459)现在作为证明尝试用这个计算器计算它,你将在程序员模式下得到-3750763034362895579(签名)而不是14695981039346656037(无符号),但是在科学模式下它是正确的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM