2014-11-12 9 views
14

python 3.4, Windows 10, Cython 0.21.1OverflowError si verifica quando si utilizza Cython con una grande int

Sto compilando questa funzione per c con Cython

def weakchecksum(data): 
    """ 
    Generates a weak checksum from an iterable set of bytes. 
    """ 
    cdef long a, b, l 
    a = b = 0 
    l = len(data) 
    for i in range(l): 
     a += data[i] 
     b += (l - i)*data[i] 

    return (b << 16) | a, a, b 

che produce questo errore: " OverflowError: Python int troppo grande per la conversione in C lungo "

Ho anche provato a dichiararli come unsigned long. Che tipo uso per lavorare con numeri veramente grandi? Se è troppo grande per un c lungo ci sono soluzioni alternative?

+0

Che ne dici di 'cdef long long'? – szxk

+0

stesso errore, il numero che lo sta causando è 2891688164113197 – user2682863

+0

Considera di fare una grande classe intera? Sarà un elenco collegato che contiene le cifre –

risposta

6

Se ci si assicura che i calcoli siano in c (ad esempio, dichiari che sia lungo, e metti l'elemento di dati in una variabile cdefed o lo lanci prima del calcolo), non otterrai questo errore. I tuoi risultati effettivi, tuttavia, potrebbero variare a seconda della piattaforma, a seconda (potenzialmente) del codice di assemblaggio esatto generato e del conseguente trattamento degli overflow. Ci sono algoritmi migliori per questo, come ha notato @ cod3monk3y (guarda il link "Simple checksums").

+0

Quindi ho aggiunto "i" all'istruzione cdef e l'ho ri-eseguito. Ho ancora lo stesso errore. Ho anche provato cdef long long a, b, l, i – user2682863

+0

Prova 'cdef long d ...' (e in loop) 'd = data [i]' oppure usa quindi 'd' nel calcolo (o usa' < > data [i] '). Puoi compilare con un flag per guardare le righe di codice w/python generate nel codice c attuale nei commenti - dovresti vedere che il calcolo è un'espressione straight c quando non ci sono variabili python coinvolte. (nota il cast non posso scrivere direttamente nel markup per qualche ragione :)) – shaunc

+0

perfetto .. Avevo rinunciato a una risposta per questo. Questo è stato. Sei un genio. Per quelli di voi che leggono questo in futuro. Ho dichiarato cdef long a, b, l, i, d, e cambiato ogni riferimento ai dati da [i] a d. – user2682863

4

Cython compila pyx file C, quindi dipende dalla sottostante compilatore C.

La dimensione dei tipi di intero in C varia su piattaforme e sistemi operativi diversi e lo standard C non determina l'implementazione esatta.

Tuttavia esistono convenzioni di attuazione di fatto.

Windows per 32 e 64 bit utilizza 4 byte (32 bit) per int e long, 8 byte (64 bit) per long long. La differenza tra Win32 e Win64 è la dimensione del puntatore (32 bit per Win32 e 64 bit per Win64). (Vedere Data Type Ranges] da MSDN).

Linux utilizza un altro modello: int è a 32 bit per entrambi linux-32 e linux-64, long long è sempre a 64 bit. long e i puntatori sono diversi: 32 bit su linux-32 e 64 bit su linux-64.

Per farla breve: se è necessaria la capacità massima per il tipo intero che non viene modificata su piattaforme diverse, utilizzare long long (o unsigned long long).

L'intervallo di dati per long long è [–9223372036854775808, 9223372036854775807].

Se sono necessari numeri con precisione arbitraria, lo standard è GMP library - per l'aritmetica di alta precisione. Python ha wrapper per questo chiamato gmpy2.

Problemi correlati