2012-04-24 22 views
5

sto cercando di definire una costante a Delfi:Come dichiarare una costante Int64?

const 
    FNV_offset_basis = 14695981039346656037; 

e ottengo l'errore: costante intera troppo grande

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

come posso dichiarare questo Int64 costante?

Alcune altre cose che ho provato:

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; 

Correzione

mio assunto fondamentale era sbagliato.

incollare 14695981039346656037 in Windows 7 Calcolatrice, e la conversione in esadecimale, mi ha portato a credere che l'equivalente esadecimale di 14695981039346656037 è 0x14650FB0739D0383:

enter image description here

Questo non è corretto.

così quando ho visto un valore esadecimale a 16 cifre, con il bit alto non impostato, ho presunto che potrebbe andare bene in un 64-bit firmato intero.

In realtà l'equivalente esadecimale di 14695981039346656037 è ... qualcos'altro. Rob, avevi ragione! (probabilmente)

+0

Hai provato: 'FNV_offset_basis = $ 14650FB0739D0383;' –

+0

possibile duplicato di [Come definire un numero intero a 64 bit senza segno in Delphi7?] (Http://stackoverflow.com/questions/6378107/how-to-define -an-unsigned-64-bit-integer-in-delphi7) – RRUZ

+1

Per la registrazione: "FNV_offset_basis = 14695981039346656037" funziona in Delphi XE2. – Giel

risposta

11

La conversione esadecimale nella domanda non è corretta. Quel numero è in realtà $ cbf29ce484222000 e non si adatta a un intero con segno a 64 bit. Avresti bisogno di un intero a 64 bit senza segno per rappresentarlo. Non vi è alcun UInt64 non firmato in Delphi 5 e quindi siete fuori di fortuna. Non esiste un tipo di dati integrale che possa rappresentare quel numero nella tua versione di Delphi.

È possibile interpretare il modello di bit come un valore con segno se ciò fa ciò che è necessario. In tal caso avresti un numero negativo.

+0

Il numero è firmato e si adatta, firmato, in un Int64. –

+0

Non va bene. È cbf29ce484222000 –

+0

Sei corretto. Fondamentalmente ho solo bisogno di memorizzare i 64 bit in una variabile a 64 bit abbastanza a lungo da eseguire un'operazione 'mod' su di essa (ma fondamentalmente). Qual è il valore decimale di '$ cbf29ce484222000' quando si assume che sia un numero intero * firmato * a 64 bit? –

5

Quel numero è più grande di un numero intero a 64 bit firmato può contenere. Hai provato a utilizzare UInt64?

+2

Delphi 5 (1999) e 7 (2002) hanno entrambi 'Int64', ma nessuno dei due ha' UInt64'. Le versioni moderne di Delphi, tuttavia. :) –

5

avevo solo bisogno della variabile 64-bit per contenere un numero a 64 bit (senza segno). È ancora possibile utilizzare Delphi di Int64 per realizzarlo, ma il trucco è stato come dichiarare le mie costanti necessari:

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

(grazie per Dave e Rob per trovare me il valore corretto esadecimale)

mentre io am, a rigor di termini, non si utilizza il Int64, sto usando un oggetto 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; 

Con alcuni cura artigianale UInt64Xxx routine matematiche:

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; 

lascerò l'implementazione UInt64Mul come esercizio per il lettore.

-1

Il calcolatore di Windows 7 è difettoso e toglie l'ultima cifra senza preavviso anche la calcolatrice sembra non essere in grado di calcolare realmente a 64 bit anche se QWord è selezionato. Sembra essere una calcolatrice Int64 solo in Windows 7 e inoltre non è in grado di visualizzare un numero sufficiente di cifre e semplicemente le elimina in un valore completamente errato. È interessante notare che il calcolatore di Windows XP non ha questo bug.

E il vero valore esadecimale del 14695981039346656037 è 0xCBF29CE484222325 anche 14695981039346656037 = (20921 * 465383 * 1509404459) ora come una prova cercare di calcolare con questa calcolatrice e otterrete -3750763034362895579 (firmato) al posto di 14695981039346656037 (non firmato) in Modalità programmatore, ma sarà corretta in modalità scientifica.

+0

@Amenom che dovresti sforzarti di unire i tuoi account. Si prega di utilizzare il [modulo di contatto] (http://stackoverflow.com/contact) – Vogel612

0

ho avuto una chiamata di WMI che ha restituito una variante di tipo Uint64 non supportato da Delphi 5. assumendo che Int64 era abbastanza giusto per il risultato che mi aspettavo, 1- I Typecasted e memorizzato il Variante tornato in un esteso (Tipo reale), 2- Ho usato la funzione "Trunc" che restituisce un Int64 da un Extended quando necessario.

Non esattamente quello che si vuole, ma considerando i Tipi reali potrebbe aiutare qualcuno a raggiungere una matematica "impossibile" Delphi 5.

Problemi correlati