2015-11-10 14 views
8

Sto costruendo un Lisp e voglio che i numeri interi a 32 bit passino automaticamente a numeri interi a 64 bit se un calcolo causerebbe un overflow. Allo stesso modo, per overflow a 64 bit, passare a numeri interi di dimensioni arbitrarie.Rileva overflow int. Firmato in Go

Il problema che ho è che non so quale sia il modo "corretto" per rilevare un overflow di numeri interi.

a, b := 2147483647, 2147483647 
c := a + b 

Come posso controllare in modo efficiente se c è in overflow?

Ho considerato sempre la conversione a 64 bit per eseguire il calcolo, quindi ridimensionare di nuovo in seguito quando possibile, ma ciò sembra costoso e la memoria sprecona per qualcosa che è primitivo e fondamentale per il linguaggio come aritmetica di base.

+0

Ho il sospetto boxe up è la soluzione migliore. Non esiste alcun meccanismo nel linguaggio proprio per mantenere l'aggiunta veloce. – captncraig

+1

Penso che i 4 byte in più siano quasi trascurabili nella maggior parte dei sistemi moderni per utilizzare solo numeri interi a 64 bit contro 32 bit nella maggior parte delle situazioni (eccezioni fatte per array di grandi dimensioni, ecc.). Per quanto riguarda il rilevamento automatico del tempo di esecuzione dell'overflow senza ricorrere all'assemblaggio, e se il proprio ambiente non genera un'eccezione da catturare, non è banale. A PARER MIO. – Alderin

+0

Conversione a 64-bit * solo per il calcolo * non ha praticamente alcun impatto sulla memoria, dal momento che si tiene solo un numero costante di valori aggiornati alla volta. Questo è, per esempio, OpenJDK's ['Math.multiplyExact (int, int)'] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java /lang/Math.java#864) fa. – user2357112

risposta

5

Ad esempio, per rilevare integer overflow 32 bit per l'aggiunta,

package main 

import (
    "errors" 
    "fmt" 
    "math" 
) 

var ErrOverflow = errors.New("integer overflow") 

func Add32(left, right int32) (int32, error) { 
    if right > 0 { 
     if left > math.MaxInt32-right { 
      return 0, ErrOverflow 
     } 
    } else { 
     if left < math.MinInt32-right { 
      return 0, ErrOverflow 
     } 
    } 
    return left + right, nil 
} 
func main() { 
    var a, b int32 = 2147483327, 2147483327 
    c, err := Add32(a, b) 
    if err != nil { 
     // handle overflow 
     fmt.Println(err, a, b, c) 
    } 
} 

uscita:

integer overflow 2147483327 2147483327 0 
+0

Grazie! Penso che potrei avere una soluzione più breve, ma non sono sicuro che ci siano casi limite in cui non funziona: '((c d11wtq

Problemi correlati