Verifica dimensione intero

di il
15 risposte

Verifica dimensione intero

Ciao,
devo fare un controllo su delle operazioni (somme sottrazioni ecc.) e devo inserire un controllo che mi dica "OVERFLOW" nel caso in cui il risultato dell'operazione ha un valore maggiore di 2147483647, cioè il numero massimo rappresentabile con un intero. Il problema è che se il risultato supera questo valore assume un valore negativo(e quindi mi rientra in un altro caso di risultato negativo), quindi non posso fare
if(risultato > 2147483647)
printf("OVERFLOW");

Come potrei fare?
PS: non devo fare un controllo sugli operandi, ma solo sul risultato finale.

15 Risposte

  • Re: Verifica dimensione intero

    Se sommi due valori positivi e il risultato è negativo, hai un overflow
    Similmente se sommi due valori negativi e hai un risultato positivo
  • Re: Verifica dimensione intero

    Giusto, potevo arrivarci. grazie
  • Re: Verifica dimensione intero

    Giuso ha scritto:


    Ciao,
    devo fare un controllo su delle operazioni (somme sottrazioni ecc.) e devo inserire un controllo che mi dica "OVERFLOW" nel caso in cui il risultato dell'operazione ha un valore maggiore di 2147483647, cioè il numero massimo rappresentabile con un intero. Il problema è che se il risultato supera questo valore assume un valore negativo(e quindi mi rientra in un altro caso di risultato negativo), quindi non posso fare
    if(risultato > 2147483647)
    printf("OVERFLOW");

    Come potrei fare?
    PS: non devo fare un controllo sugli operandi, ma solo sul risultato finale.
    Il fatto è che l'overflow di una somma tra interi è undefined behaviour pertanto controllare il risultato finale non è sempre una buona idea perché non è detto che i suddetti interi siano rappresentati per forza in complemento a 2
  • Re: Verifica dimensione intero

    Si potrebbe fare così?
    #include <stdint.h>
    
    int somma_con_controllo_overflow( int32_t *somma, int32_t a, int32_t b ) {
        int64_t somma_tmp = (int64_t)a + (int64_t)b;
    
        if( somma_tmp >= -0x80000000LL && somma_tmp < 0x80000000LL ) {
            *somma = (int32_t)somma_tmp;
            return 0;
        }
    
        return 1;
    }
  • Re: Verifica dimensione intero

    AldoBaldo ha scritto:


    Si potrebbe fare così?
    Se usi interi a 64 bit è ovvio.

    Ma se non li puoi usare perché il compilatore non li supporta?
  • Re: Verifica dimensione intero

    Cambi compilatore? Oppure, se costretto, definisci dei tipi appositi e scrivi delle funzioni per maneggiarli? Se non sbaglio i più comuni sistemi operativi dispongono di API predefinite, finalizzate proprio a quello.

    Un'altra via potrebbe essere quella di osservare certi bit "strategici" nei valori da sommare? (anche se, concretamente e sui due piedi, non ho idea di come si potrebbe fare)

    Se conosci delle alternative, perché non ce le proponi? Io seguo e leggo.
  • Re: Verifica dimensione intero

    AldoBaldo ha scritto:


    Cambi compilatore? Oppure ...
    Non limitare il pensiero ai PC ... esistono tanti ambiti, micro a 32 bit con compilatori C, ovviamente, a 32 bit, ad esempio.

    I bit che si osservano, appunto, sono quelli dei segni. Non è che ci siano alternative.
  • Re: Verifica dimensione intero

    Io viste le considerazioni di sopra farei così sinceramente:
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <stdbool.h>
    
    int main(void)
    {
        int a = 10394;
        int b = 5;
        bool is_overflow;
    
        if ((a ^ b) < 0) {
            is_overflow = false;
        }
        else if (a > 0) { 
            is_overflow= (b > (INT_MAX - a));
        }
        else {
            is_overflow = (b < (INT_MIN - a));
        }
    
        if(is_overflow) {
            puts("Overflow detected");
        }
        else {
            printf("La somma di %d e %d e': %d\n",
            a, b, a + b);
        }
    
        return EXIT_SUCCESS;
    }
  • Re: Verifica dimensione intero

    @oregon
    La soluzione di IfNotFalseTrue rientra tra quelle alle quali ti riferisci?

    @IfNotFalseTrue
    Forte! Anche perché, se ho capito bene, a quel modo puoi usare il procedimento sia in ambiente a 32 bit ma anche a 16, o 64 o addirittura 8 bit (purché compilatore e librerie standard siano adeguate).

    Due cose...

    La prima: (a ^ b) < 0 serve a verificare se il segno è positivo o negativo, vero? Se e' così, mi sfugge perché non hai usato un più sempice (da leggere) (a>=0)&&(b>=0). Se non è così, mi spieghi a cosa serve?

    La seconda: può andar bene anche fare una macro così?
    #define IS_OVERFLOW(a,b) ((int)a^(int)b)<0?0:((int)a>0?((int)b>(INT_MAX-(int)a)):((int)b<(INT_MIN-(int)a)))
    
    // tutti quei cast a int sono indispensabili, in questo caso?
    Nelle intenzioni dovrebbe restituire 0 se a e b si possono sommare senza andare in overflow, e 1 se invece sommarli porta a un overflow.
  • Re: Verifica dimensione intero

    Io direi più semplicemente
    
    bool sum(int a, int b, int *res)
    {
    	bool ov = false;
    	*res = a + b;
    	
    	if (
    		(a > 0 && b > 0 && *res < 0) || 
    		(a < 0 && b < 0 && *res > 0)
    	   ) ov = true;
    
    	return ov;
    }
    
  • Re: Verifica dimensione intero

    @oregon

    Ma... prima IfNotFalseTrue ci diceva che "l'overflow di una somma tra interi è undefined behaviour pertanto controllare il risultato finale non è sempre una buona idea perché non è detto che i suddetti interi siano rappresentati per forza in complemento a 2"...

    [manca l'emoticon di quello che si gratta la cocuzza]
  • Re: Verifica dimensione intero

    Chi ha creato il thread usa il C2 evidentemente.

    E non mi pare che il codice proposto sia valido per qualsiasi tipo di rappresentazione.

    Del resto limitare la questione al C2 non è un gran problema.
  • Re: Verifica dimensione intero

    AldoBaldo ha scritto:


    @oregon

    Ma... prima IfNotFalseTrue ci diceva che "l'overflow di una somma tra interi è undefined behaviour pertanto controllare il risultato finale non è sempre una buona idea perché non è detto che i suddetti interi siano rappresentati per forza in complemento a 2"...

    [manca l'emoticon di quello che si gratta la cocuzza]
    Non lo dico io, lo dice lo standard:
    3.4.3
    1 undefined behavior
    behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
    for which this International Standard imposes no requirements
    2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
    results, to behaving during translation or program execution in a documented manner characteristic of the
    environment (with or without the issuance of a diagnostic message), to terminating a translation or
    execution (with the issuance of a diagnostic message).
    3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

    AldoBaldo ha scritto:


    @oregon
    La soluzione di IfNotFalseTrue rientra tra quelle alle quali ti riferisci?

    @IfNotFalseTrue
    Forte! Anche perché, se ho capito bene, a quel modo puoi usare il procedimento sia in ambiente a 32 bit ma anche a 16, o 64 o addirittura 8 bit (purché compilatore e librerie standard siano adeguate).

    Due cose...

    La prima: (a ^ b) < 0 serve a verificare se il segno è positivo o negativo, vero? Se e' così, mi sfugge perché non hai usato un più sempice (da leggere) (a>=0)&&(b>=0). Se non è così, mi spieghi a cosa serve?

    La seconda: può andar bene anche fare una macro così?
    #define IS_OVERFLOW(a,b) ((int)a^(int)b)<0?0:((int)a>0?((int)b>(INT_MAX-(int)a)):((int)b<(INT_MIN-(int)a)))
    
    // tutti quei cast a int sono indispensabili, in questo caso?
    Nelle intenzioni dovrebbe restituire 0 se a e b si possono sommare senza andare in overflow, e 1 se invece sommarli porta a un overflow.
    Una macro di quel genere a me non piacerebbe peraltro è fuorviante perché INT_MAX ed INT_MIN perché sono il valore massimo e minimo rappresentabili dal tipo int per cui castare ad int non ha senso, a e b devono essere per forza int, altrimenti non è detto che funzioni correttamente
  • Re: Verifica dimensione intero

    Grazie If. Allora, faccio direttamente un cast della macro nella sua interezza => casted into the bin.
Devi accedere o registrarti per scrivere nel forum
15 risposte