Come ti guardi dagli overflow nascosti

1

considera quanto segue:

(i+j)/2

i e j sono entrambi numeri interi a 32 bit e anche il risultato dovrebbe essere. Ma nella piccola equazione, c'è un overflow nascosto, i + j potrebbe diventare più grande di un intero a 32 bit anche se il risultato sarebbe sempre un intero a 32 bit.

public class Sum{
     public static void main(String []args){
        int i = 2147483647;
        int j = 2147483647;                       
        System.out.println((i + j)/2);
     }
}

Mi dà -1 come risultato.

Come proteggersi da situazioni che possono traboccare ma non sono sempre evidenti. C'è uno schema che descrive questo?

(a parte dichiarare tutto a lungo)

Sto cercando una risposta generale, l'esempio java è solo per fornire un esempio, il mio Delphi fa lo stesso.

    
posta Pieter B 13.08.2014 - 13:22
fonte

2 risposte

7

Hai tre scelte, nessuna delle quali è l'ideale per tutte le situazioni:

Rileva overflow. La maggior parte delle lingue consente di determinare il valore più ampio possibile per i tipi di dati interi. L'aggiunta nel tuo esempio genererà un overflow ogni volta che j > (max_value_of_type - i) . Dovrai controllare ogni utilizzo per gli overflow o creare una libreria o una classe per farlo per te.

Utilizza tipi più grandi. se sono disponibili numeri interi più grandi, utilizza quelli per eseguire i calcoli intermedi e converti nuovamente al tipo più piccolo una volta terminato. L'intoppo qui è che devi capire se i risultati di quei calcoli sono garantiti per adattarsi alle dimensioni più piccole se è quello che restituirai. Il tuo esempio di (i + j) / 2 si adatta, ma (i * j) / 2 no.

Limita i valori di input. Questo è molto simile a entrambi i precedenti in quanto stai limitando gli input a valori che sai non causeranno un overflow e allo stesso tempo facendo gli interi abbastanza grande da contenere il risultato.

    
risposta data 13.08.2014 - 14:30
fonte
1

Puoi definire i tuoi operatori aritmetici, ad esempio in questo modo.

int operator + (int a, int b) {
    int res = a + b;
    if(a > 0 && b > 0 && res < 0) {
        throw new ArithmeticOverflowException();
    } else if(a < 0 && b < 0 && res > 0) {
        throw new ArithmeticUnderflowException();
    }
    return res;
}
    
risposta data 13.08.2014 - 14:12
fonte