2012-04-24 11 views
5

Ich versuche, eine Konstante in Delphi zu definieren:Wie deklariert man eine Int64-Konstante?

const 
    FNV_offset_basis = 14695981039346656037; 

Und ich den Fehler: Integer konstant zu groß

Note:14,695,981,039,346,656,037 decimal is equal to 0x14650FB0739D0383 hex.

Wie kann ich erklären, diese Int64 konstant?

einige andere Dinge, die ich versucht habe:

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; 

Korrektur

Meine Grundannahme falsch war.

Einfügen 14695981039346656037 in Windows 7 Rechner, und Hex-Umwandlung, mich zu glauben, dass die Hex-Äquivalent 14695981039346656037 ist 0x14650FB0739D0383:

enter image description here

Das ist falsch.

Also, wenn ich einen Wert 16-stellige Hex sah, mit dem hohen Bit nicht gesetzt, ich vermute es in einem 64-Bit passen könnte unterzeichnet integer.

In Wirklichkeit ist das Hexadezimaläquivalent von 14695981039346656037 ... etwas anderes. Rob, du hattest Recht! (wahrscheinlich)

+0

Haben Sie versucht: 'FNV_offset_basis = $ 14650FB0739D0383;' –

+0

möglich Duplikat [Wie eine nicht signierte 64-Bit-Integer in Delphi7 definieren?] (Http://stackoverflow.com/questions/6378107/how-to-define -an-unsigned-64-bit-integer-in-delphi7) – RRUZ

+1

Für den Datensatz: "FNV_offset_basis = 14695981039346656037" funktioniert in Delphi XE2. – Giel

Antwort

11

Ihre Hex-Konvertierung in der Frage ist falsch. Diese Zahl ist tatsächlich $ cbf29ce484222000 und passt nicht in eine 64-Bit-Ganzzahl mit Vorzeichen. Sie benötigen eine vorzeichenlose 64-Bit-Ganzzahl, um sie darzustellen. Es gibt kein unsigniertes UInt64 in Delphi 5 und du hast kein Glück. Es gibt keinen integralen Datentyp, der diese Zahl in Ihrer Version von Delphi darstellen kann.

Sie könnten das Bitmuster möglicherweise als einen signierten Wert interpretieren, wenn das tut, was Sie brauchen. In diesem Fall hätten Sie eine negative Nummer.

+0

Die Nummer ist signiert und passt, signiert, in einen Int64. –

+0

Es passt nicht. Es ist cbf29ce484222000 –

+0

Sie haben Recht. Grundsätzlich muss ich nur die 64-Bit in einer 64-Bit-Variablen nur lange genug speichern, um eine "mod" -Operation darauf auszuführen (aber grundsätzlich). Was ist der Dezimalwert von '$ cbf29ce484222000', wenn angenommen wird, dass es sich um eine * signierte * 64-Bit-Ganzzahl handelt? –

5

Diese Zahl ist größer als eine vorzeichenbehaftete 64-Bit-Ganzzahl halten kann. Haben Sie stattdessen versucht, UInt64 zu verwenden?

+2

Delphi 5 (1999) und 7 (2002) haben beide 'Int64', aber keiner hat' UInt64'. Moderne Delphi-Versionen tun dies jedoch. :) –

5

Ich brauchte nur die 64-Bit-Variable, um eine 64-Bit (unsigned) Nummer zu halten. ich kann immer noch verwenden Delphi Int64 es zu erreichen, aber der Trick war, wie meine benötigten Konstanten deklarieren:

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

(vielen Dank für Dave und Rob für mich den richtigen Hex-Wert zu finden)

Während i Uhr, streng genommen, nicht die Int64 mit, ich bin mit einem 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; 

Mit einigen sorgfältig gestalteten UInt64Xxx mathematischen Routinen:

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; 

Ich werde die Implementierung UInt64Mul als Übung für den Leser verlassen.

-1

Der Windows 7 Calculator ist fehlerhaft und streift die letzte Ziffer ohne Warnung auch der Rechner scheint nicht in der Lage 64Bits wirklich zu berechnen, auch wenn QWord ausgewählt ist. Es scheint ein Int64 Calculator nur in Windows 7 zu sein und es kann auch nicht genug Ziffern anzeigen und streift sie einfach zu einem völlig falschen Wert. Interessanterweise hat der Windows XP Rechner diesen Bug nicht.

Und der wirkliche Hex-Wert von 14695981039346656037 ist 0xCBF29CE484222325 auch 14695981039346656037 = (20921 * 465383 * 1509404459) jetzt als Beweis es mit diesem Rechner zu berechnen versuchen, und Sie werden -3750763034362895579 (signiert) anstelle von 14695981039346656037 (unsigned) erhalten in Programmer Mode, aber es wird im Scientific Mode korrekt sein.

+0

@Amenom sollten Sie sich bemühen, Ihre Konten zusammenzuführen. Bitte benutzen Sie das [Kontaktformular] (http://stackoverflow.com/contact) – Vogel612

0

hatte ich einen WMI-Aufruf, der eine Variante des Typs UINT64 zurückgegeben nicht von Delphi unterstützt 5. Unter der Annahme, dass Int64 fair genug für das Ergebnis war ich erwartet hatte, 1- ich die zurück Variant in einen erweiterten Typecasted und gespeichert (Realer Typ), 2- Ich benutzte die Funktion "Trunc", die bei Bedarf einen Int64 von einem Extended zurückgibt.

Nicht genau das, was Sie wollen, aber in Anbetracht der Real-Typen könnte jemand helfen, einige "unmögliche" Delphi 5 Mathe zu erreichen.