In che modo Java gestisce i underflow e gli overflow di numeri interi e come si controlla?


226

In che modo Java gestisce i underflow e gli overflow di numeri interi?

Partendo da questo, come verificherebbe / testereste che ciò accada?


28
Peccato che Java non fornisca accesso indiretto al flag di overflow della CPU , come avviene in C # .
Drew Noakes,

@DrewNoakes Ed è un peccato che C # non sia inadempiente per checkedquanto ne so. Non lo vedo usato molto, e digitare checked { code; }è tanto lavoro quanto chiamare un metodo.
Maarten Bodewes,

2
@MaartenBodewes, è possibile impostarlo come predefinito durante la compilazione di un assemblye. csc /checked ...oppure imposta la proprietà nel riquadro delle proprietà del progetto in Visual Studio.
Drew Noakes,

@DrewNoakes OK, interessante. Un po 'strano che si tratti di un'impostazione al di fuori del codice. In generale, vorrei avere lo stesso comportamento di un programma indipendentemente da tali impostazioni (possibilmente tranne le asserzioni).
Maarten Bodewes,

@MaartenBodewes, penso che il ragionamento sia che ci sia un sovraccarico perf non banale per il controllo. Quindi forse lo abiliteresti nelle build di debug, quindi lo disabiliterai nelle build di rilascio, proprio come molti altri tipi di asserzioni.
Drew Noakes,

Risposte:


217

Se trabocca, ritorna al valore minimo e continua da lì. Se underflow, torna al valore massimo e continua da lì.

Puoi verificarlo in anticipo come segue:

public static boolean willAdditionOverflow(int left, int right) {
    if (right < 0 && right != Integer.MIN_VALUE) {
        return willSubtractionOverflow(left, -right);
    } else {
        return (~(left ^ right) & (left ^ (left + right))) < 0;
    }
}

public static boolean willSubtractionOverflow(int left, int right) {
    if (right < 0) {
        return willAdditionOverflow(left, -right);
    } else {
        return ((left ^ right) & (left ^ (left - right))) < 0;
    }
}

(è possibile sostituire intda longper eseguire gli stessi controlli perlong )

Se ritieni che ciò possa verificarsi più spesso, prendi in considerazione l'utilizzo di un tipo di dati o un oggetto in grado di memorizzare valori più grandi, ad esempio longo forse java.math.BigInteger. L'ultimo non trabocca, praticamente, la memoria JVM disponibile è il limite.


Se ti trovi già su Java8, puoi usare il nuovo Math#addExact()e i Math#subtractExact()metodi che genereranno un ArithmeticExceptionoverflow.

public static boolean willAdditionOverflow(int left, int right) {
    try {
        Math.addExact(left, right);
        return false;
    } catch (ArithmeticException e) {
        return true;
    }
}

public static boolean willSubtractionOverflow(int left, int right) {
    try {
        Math.subtractExact(left, right);
        return false;
    } catch (ArithmeticException e) {
        return true;
    }
}

Il codice sorgente può essere trovato qui e qui rispettivamente.

Naturalmente, puoi anche usarli subito invece di nasconderli in un booleanmetodo di utilità.


13
@dhblah, diciamo che i valori massimo e minimo consentiti da Java per un int sono +100, -100, rispettivamente. Se ne aggiungessi uno a un numero intero Java, il processo sarebbe simile a questo quando traboccava. 98, 99, 100, -100, -99, -98, .... Ha più senso?
Austin A

6
Consiglio di utilizzare i metodi di utilità invece di utilizzare subito il codice. I metodi di utilità sono intrinseci e saranno sostituiti dal codice specifico della macchina. Un test rapido ha mostrato che Math.addExact è il 30% più veloce di un metodo copiato (Java 1.8.0_40).
TilmannZ,

1
@ErikE Math#addExactè la sintassi normalmente usata quando si scrive javadocs - mentre normalmente dovrebbe essere convertita Math.addExact, a volte l'altra forma
rimane invariata

1
If it underflows, it goes back to the maximum value and continues from there.- sembra che tu abbia confuso underflow con overflow negativo. underflow in numeri interi si verifica sempre (quando il risultato è una frazione).
navata

1
en.wikipedia.org/wiki/Arithmetic_underflow afferma che Underflow è una condizione in un programma per computer in cui il risultato di un calcolo è un numero di valore assoluto più piccolo di quello che il computer può effettivamente rappresentare in memoria sulla sua CPU. Pertanto, il underflow non si applica a Integer Java. @BalusC
Yao

66

Bene, per quanto riguarda i tipi interi primitivi, Java non gestisce affatto Over / Underflow (per il float e il doppio il comportamento è diverso, arriverà a +/- infinito proprio come IEEE-754 impone).

Quando aggiungi due int, non otterrai alcuna indicazione quando si verifica un overflow. Un metodo semplice per verificare l'overflow consiste nell'utilizzare il tipo più grande successivo per eseguire effettivamente l'operazione e verificare se il risultato è ancora nell'intervallo per il tipo di origine:

public int addWithOverflowCheck(int a, int b) {
    // the cast of a is required, to make the + work with long precision,
    // if we just added (a + b) the addition would use int precision and
    // the result would be cast to long afterwards!
    long result = ((long) a) + b;
    if (result > Integer.MAX_VALUE) {
         throw new RuntimeException("Overflow occured");
    } else if (result < Integer.MIN_VALUE) {
         throw new RuntimeException("Underflow occured");
    }
    // at this point we can safely cast back to int, we checked before
    // that the value will be withing int's limits
    return (int) result;
}

Che cosa faresti al posto delle clausole di lancio, dipende dai requisiti delle tue applicazioni (lancio, scarica al minimo / massimo o registra semplicemente). Se vuoi rilevare l'overflow in operazioni lunghe, sei sfortunato con le primitive, usa invece BigInteger.


Modifica (21-05-2014): poiché questa domanda sembra essere citata abbastanza frequentemente e ho dovuto risolvere da solo lo stesso problema, è abbastanza facile valutare la condizione di overflow con lo stesso metodo con cui una CPU calcolerebbe il suo flag V.

Fondamentalmente è un'espressione booleana che coinvolge sia il segno di entrambi gli operandi che il risultato:

/**
 * Add two int's with overflow detection (r = s + d)
 */
public static int add(final int s, final int d) throws ArithmeticException {
    int r = s + d;
    if (((s & d & ~r) | (~s & ~d & r)) < 0)
        throw new ArithmeticException("int overflow add(" + s + ", " + d + ")");    
    return r;
}

In java è più semplice applicare l'espressione (in if) a tutti i 32 bit e controllare il risultato usando <0 (questo testerà effettivamente il bit del segno). Il principio funziona esattamente allo stesso modo per tutti i tipi primitivi interi , modificando tutte le dichiarazioni del metodo sopra in long lo fa funzionare a lungo.

Per tipi più piccoli, a causa della conversione implicita in int (per i dettagli vedere JLS per operazioni bit a bit), invece di controllare <0, il controllo deve mascherare esplicitamente il bit di segno (0x8000 per operandi brevi, 0x80 per operandi byte, regolare i cast e la dichiarazione dei parametri opportunamente):

/**
 * Subtract two short's with overflow detection (r = d - s)
 */
public static short sub(final short d, final short s) throws ArithmeticException {
    int r = d - s;
    if ((((~s & d & ~r) | (s & ~d & r)) & 0x8000) != 0)
        throw new ArithmeticException("short overflow sub(" + s + ", " + d + ")");
    return (short) r;
}

(Si noti che l'esempio sopra utilizza l'espressione necessità di sottrarre il rilevamento di overflow)


Quindi come / perché funzionano queste espressioni booleane? Innanzitutto, un certo pensiero logico rivela che un overflow può verificarsi solo se i segni di entrambi gli argomenti sono gli stessi. Perché, se un argomento è negativo e uno positivo, il risultato (di add) deve essere più vicino a zero, o nel caso estremo un argomento è zero, lo stesso dell'altro argomento. Poiché gli argomenti da soli non possono creare una condizione di overflow, neanche la loro somma può creare un overflow.

Quindi cosa succede se entrambi gli argomenti hanno lo stesso segno? Diamo un'occhiata al caso entrambi sono positivi: l'aggiunta di due argomenti che creano una somma maggiore dei tipi MAX_VALUE, produrrà sempre un valore negativo, quindi si verifica un overflow se arg1 + arg2> MAX_VALUE. Ora il valore massimo che potrebbe risultare sarebbe MAX_VALUE + MAX_VALUE (nel caso estremo entrambi gli argomenti sono MAX_VALUE). Per un byte (esempio) che significherebbe 127 + 127 = 254. Osservando le rappresentazioni dei bit di tutti i valori che possono derivare dall'aggiunta di due valori positivi, si scopre che quelli che superano (da 128 a 254) hanno tutti impostato il bit 7, mentre tutto quello che non trabocca (da 0 a 127) ha il bit 7 (più in alto, segno) cancellato. Questo è esattamente ciò che controlla la prima parte (destra) dell'espressione:

if (((s & d & ~r) | (~s & ~d & r)) < 0)

(~ s & ~ d & r) diventa vero, solo se entrambi gli operandi (s, d) sono positivi e il risultato (r) è negativo (l'espressione funziona su tutti e 32 i bit, ma l'unico bit a cui siamo interessati è il bit (segno) più in alto, che viene verificato da <0).

Ora, se entrambi gli argomenti sono negativi, la loro somma non può mai essere più vicina allo zero di qualsiasi argomento, la somma deve essere più vicina al meno infinito. Il valore più estremo che possiamo produrre è MIN_VALUE + MIN_VALUE, che (sempre per esempio byte) mostra che per qualsiasi valore compreso nell'intervallo (da -1 a -128) viene impostato il bit di segno, mentre ogni possibile valore di overflow (da -129 a -256 ) ha il bit di segno cancellato. Quindi il segno del risultato rivela di nuovo la condizione di overflow. Questo è ciò che la metà sinistra (s & d & ~ r) controlla per il caso in cui entrambi gli argomenti (s, d) sono negativi e un risultato positivo. La logica è ampiamente equivalente al caso positivo; tutti i pattern di bit che possono derivare dall'aggiunta di due valori negativi avranno il bit di segno cancellato se e solo se si è verificato un underflow.


1
Puoi verificarlo con operatori bit per bit, nonché betterlogic.com/roger/2011/05/…
rogerdpack,

1
Funzionerà ma suppongo che avrà un brutto colpo di prestazione.
chessofnerd,

33

Per impostazione predefinita, int e la matematica lunga di Java si chiudono silenziosamente su overflow e underflow. (Le operazioni intere su altri tipi interi vengono eseguite promuovendo prima gli operandi a int o long, secondo JLS 4.2.2 .)

Come di Java 8, java.lang.Mathfornisce addExact, subtractExact, multiplyExact, incrementExact, decrementExactenegateExact metodi statici sia per int e lunghe discussioni che eseguono l'operazione denominata, gettando ArithmeticException in caso di overflow. (Non esiste un metodo divideExact: dovrai controllare MIN_VALUE / -1tu stesso il caso speciale ( ).)

A partire da Java 8, java.lang.Math fornisce anche il toIntExactcast di un long a un int, lanciando ArithmeticException se il valore del long non rientra in un int. Questo può essere utile, ad esempio, per calcolare la somma degli ints usando una matematica lunga non selezionata, quindi usandotoIntExact cast per int alla fine (ma fai attenzione a non far traboccare la somma).

Se stai ancora utilizzando una versione precedente di Java, Google Guava fornisce metodi statici IntMath e LongMath per addizione, sottrazione, moltiplicazione ed esponenziazione verificate (lancio di overflow). Queste classi forniscono anche metodi per calcolare fattoriali e coefficienti binomiali che ritornano MAX_VALUEin overflow (che è meno conveniente da controllare). Classi di utilità primitive di Guava, SignedBytes, UnsignedBytes, Shortse Ints, forniscono checkedCastmetodi per restringere i tipi più grandi (gettando IllegalArgumentException on sotto / troppo pieno, non ArithmeticException), così come i saturatingCastmetodi che di ritorno MIN_VALUEo MAX_VALUEin caso di overflow.


32

Java non fa nulla con overflow dei numeri interi per tipi int o long primitive e ignora l'overflow con numeri interi positivi e negativi.

Questa risposta descrive innanzitutto l'overflow degli interi, fornisce un esempio di come può accadere, anche con valori intermedi nella valutazione dell'espressione, quindi fornisce collegamenti a risorse che forniscono tecniche dettagliate per prevenire e rilevare l'overflow degli interi.

L'aritmetica intera e le espressioni che risiedono in un overflow imprevisto o non rilevato sono un errore di programmazione comune. L'overflow di numeri interi imprevisti o non rilevati è anche un noto problema di sicurezza sfruttabile, in particolare in quanto riguarda gli oggetti array, stack ed elenco.

L'overflow può verificarsi in una direzione positiva o negativa in cui il valore positivo o negativo sarebbe oltre i valori massimo o minimo per il tipo primitivo in questione. L'overflow può verificarsi in un valore intermedio durante la valutazione dell'espressione o dell'operazione e influire sul risultato di un'espressione o operazione in cui il valore finale dovrebbe rientrare nell'intervallo.

A volte l'overflow negativo viene erroneamente chiamato underflow. Underflow è ciò che accade quando un valore sarebbe più vicino a zero di quanto consentito dalla rappresentazione. Underflow si verifica in aritmetica intera ed è previsto. Il underflow di numeri interi si verifica quando una valutazione di numeri interi dovrebbe essere compresa tra -1 e 0 o 0 e 1. Quale sarebbe un risultato frazionario che viene troncato a 0. Questo è normale e previsto con l'aritmetica dei numeri interi e non considerato un errore. Tuttavia, può portare al lancio di un'eccezione nel codice. Un esempio è un'eccezione "ArithmeticException: / by zero" se il risultato del underflow intero viene utilizzato come divisore in un'espressione.

Considera il seguente codice:

int bigValue = Integer.MAX_VALUE;
int x = bigValue * 2 / 5;
int y = bigValue / x;

che si traduce in x assegnato a 0 e la successiva valutazione di bigValue / x genera un'eccezione, "ArithmeticException: / per zero" (ovvero dividere per zero), invece che y venga assegnato il valore 2.

Il risultato atteso per x sarebbe 858.993.458, che è inferiore al valore int massimo di 2.147.483.647. Tuttavia, il risultato intermedio dalla valutazione di Integer.MAX_Value * 2, sarebbe 4.294.967.294, che supera il valore int massimo ed è -2 in conformità con le rappresentazioni intere del complemento 2s. La successiva valutazione di -2 / 5 restituisce 0 che viene assegnato a x.

Riorganizzare l'espressione per calcolare x in un'espressione che, quando valutata, divide prima di moltiplicare, il seguente codice:

int bigValue = Integer.MAX_VALUE;
int x = bigValue / 5 * 2;
int y = bigValue / x;

risulta che x sia assegnato 858.993.458 e y assegnato 2, il che è previsto.

Il risultato intermedio di bigValue / 5 è 429.496.729 che non supera il valore massimo per un int. La valutazione successiva di 429.496.729 * 2 non supera il valore massimo per un int e il risultato atteso viene assegnato a x. La valutazione per y quindi non si divide per zero. Le valutazioni per xey funzionano come previsto.

I valori interi Java vengono memorizzati come e si comportano in conformità con le rappresentazioni di interi firmati con complemento a 2s. Quando un valore risultante sarebbe maggiore o minore del valore intero massimo o minimo, si ottiene invece il valore intero del complemento di 2. In situazioni non espressamente progettate per utilizzare il comportamento del complemento 2s, che è la maggior parte delle normali situazioni aritmetiche intere, il risultante valore del complemento 2s causerà una logica di programmazione o un errore di calcolo, come mostrato nell'esempio sopra. Un eccellente articolo di Wikipedia descrive qui interi binari di complimenti 2s: complemento a due - Wikipedia

Esistono tecniche per evitare l'overflow involontario di numeri interi. Le tecniche possono essere classificate come utilizzando test pre-condition, upcasting e BigInteger.

Il test pre-condizione comprende l'esame dei valori che vanno in un'operazione o espressione aritmetica per garantire che non si verifichi un overflow con tali valori. La programmazione e la progettazione dovranno creare test che assicurino che i valori di input non causino overflow e quindi determinare cosa fare se si verificano valori di input che causeranno overflow.

L'upcasting comprende l'uso di un tipo primitivo più grande per eseguire l'operazione o espressione aritmetica e quindi determinare se il valore risultante è oltre i valori massimo o minimo per un numero intero. Anche con l'upcasting, è ancora possibile che il valore o un valore intermedio in un'operazione o espressione siano oltre i valori massimi o minimi per il tipo di upcast e causino un overflow, che non verrà rilevato e causerà risultati imprevisti e indesiderati. Attraverso analisi o pre-condizioni, potrebbe essere possibile prevenire l'overflow con l'upcasting quando la prevenzione senza upcasting non è possibile o pratica. Se gli interi in questione sono già tipi primitivi lunghi, non è possibile eseguire l'upgrade con tipi primitivi in ​​Java.

La tecnica BigInteger comprende l'utilizzo di BigInteger per l'operazione o espressione aritmetica mediante metodi di libreria che utilizzano BigInteger. BigInteger non trabocca. Userà tutta la memoria disponibile, se necessario. I suoi metodi aritmetici sono normalmente solo leggermente meno efficienti delle operazioni intere. È ancora possibile che un risultato che utilizza BigInteger sia oltre i valori massimo o minimo per un numero intero, tuttavia, nell'aritmetica non si verificherà un overflow che porta al risultato. La programmazione e la progettazione dovranno ancora determinare cosa fare se un risultato BigInteger supera i valori massimo o minimo per il tipo di risultato primitivo desiderato, ad esempio int o long.

Il programma CERT del Carnegie Mellon Software Engineering Institute e Oracle hanno creato un insieme di standard per la programmazione Java sicura. Incluso negli standard sono le tecniche per prevenire e rilevare l'overflow di numeri interi. Lo standard è pubblicato come risorsa online liberamente accessibile qui: CERT Oracle Secure Coding Standard per Java

La sezione dello standard che descrive e contiene esempi pratici di tecniche di codifica per prevenire o rilevare l'overflow di numeri interi è qui: NUM00-J. Rileva o impedisce l'overflow di numeri interi

Sono inoltre disponibili il modulo libro e il modulo PDF di The CERT Oracle Secure Coding Standard per Java.


questa è la risposta migliore qui in quanto indica chiaramente che cosa è underflow (la risposta accettata non lo fa) ed elenca anche le tecniche per gestire overflow / underflow
nave

12

Avendo appena incontrato questo problema da solo, ecco la mia soluzione (sia per la moltiplicazione che per l'aggiunta):

static boolean wouldOverflowOccurwhenMultiplying(int a, int b) {
    // If either a or b are Integer.MIN_VALUE, then multiplying by anything other than 0 or 1 will result in overflow
    if (a == 0 || b == 0) {
        return false;
    } else if (a > 0 && b > 0) { // both positive, non zero
        return a > Integer.MAX_VALUE / b;
    } else if (b < 0 && a < 0) { // both negative, non zero
        return a < Integer.MAX_VALUE / b;
    } else { // exactly one of a,b is negative and one is positive, neither are zero
        if (b > 0) { // this last if statements protects against Integer.MIN_VALUE / -1, which in itself causes overflow.
            return a < Integer.MIN_VALUE / b;
        } else { // a > 0
            return b < Integer.MIN_VALUE / a;
        }
    }
}

boolean wouldOverflowOccurWhenAdding(int a, int b) {
    if (a > 0 && b > 0) {
        return a > Integer.MAX_VALUE - b;
    } else if (a < 0 && b < 0) {
        return a < Integer.MIN_VALUE - b;
    }
    return false;
}

sentiti libero di correggere se sbagliato o se può essere semplificato. Ho fatto alcuni test con il metodo di moltiplicazione, principalmente casi limite, ma potrebbe ancora essere sbagliato.


La divisione può essere lenta rispetto alla moltiplicazione. Perché int*int, penso semplicemente lanciare longe vedere se il risultato si adatta intsarebbe l'approccio più veloce. Perché long*long, se si normalizzano gli operandi come positivi, si possono dividere ciascuno in metà superiore e inferiore a 32 bit, promuovere ciascuna metà a lungo (fare attenzione alle estensioni dei segni!), Quindi calcolare due prodotti parziali [una delle metà superiori dovrebbe essere zero].
supercat,

Quando dici "A lungo * a lungo, se uno normalizza gli operandi come positivi ...", come faresti a normalizzare Long.MIN_VALUE?
Fragorl,

Questi metodi possono essere interessanti se è necessario verificare se qualcosa trabocca prima di eseguire effettivamente il calcolo. Potrebbe essere utile per testare, ad esempio, l'input dell'utente utilizzato per tali calcoli, invece di cogliere l'eccezione quando accade.
Maarten Bodewes,

8

Esistono librerie che forniscono operazioni aritmetiche sicure, che controllano l'overflow / underflow dell'intero. Ad esempio, IntMath.checkedAdd (int a, int b) di Guava restituisce la somma di ae b, purché non trabocchi, e genera ArithmeticExceptionse a + btrabocca intnell'aritmetica firmata .


Sì, questa è una buona idea, a meno che tu non sia Java 8 o superiore, nel qual caso la Mathclasse contiene un codice simile.
Maarten Bodewes,

6

Si avvolge.

per esempio:

public class Test {

    public static void main(String[] args) {
        int i = Integer.MAX_VALUE;
        int j = Integer.MIN_VALUE;

        System.out.println(i+1);
        System.out.println(j-1);
    }
}

stampe

-2147483648
2147483647

Bene! E ora, puoi rispondere, come rilevarlo in un calcolo complesso?
Aubin,

5

Penso che dovresti usare qualcosa del genere e si chiama Upcasting:

public int multiplyBy2(int x) throws ArithmeticException {
    long result = 2 * (long) x;    
    if (result > Integer.MAX_VALUE || result < Integer.MIN_VALUE){
        throw new ArithmeticException("Integer overflow");
    }
    return (int) result;
}

Puoi leggere qui di seguito: Rileva o impedisce l'overflow di numeri interi

È una fonte abbastanza affidabile.


3

Non fa nulla - il underflow / overflow succede e basta.

Un "-1" che è il risultato di un calcolo traboccato non è diverso dal "-1" risultante da qualsiasi altra informazione. Quindi non puoi dire tramite un certo stato o controllando solo un valore se è traboccato.

Ma puoi essere intelligente sui tuoi calcoli per evitare il trabocco, se è importante, o almeno sapere quando accadrà. Qual è la tua situazione?


Non è proprio una situazione, solo qualcosa di cui sono curioso e mi ha fatto pensare. Se hai bisogno di un caso d'uso di esempio, eccone uno: ho una classe con la sua variabile interna chiamata 'secondi'. Ho due metodi che prendono un numero intero come parametro e aumenteranno o diminuiranno (rispettivamente) 'secondi' di così tanto. Come testereste l'unità che si sta verificando un underflow / overflow e come evitereste?
KushalP,

1
static final int safeAdd(int left, int right)
                 throws ArithmeticException {
  if (right > 0 ? left > Integer.MAX_VALUE - right
                : left < Integer.MIN_VALUE - right) {
    throw new ArithmeticException("Integer overflow");
  }
  return left + right;
}

static final int safeSubtract(int left, int right)
                 throws ArithmeticException {
  if (right > 0 ? left < Integer.MIN_VALUE + right
                : left > Integer.MAX_VALUE + right) {
    throw new ArithmeticException("Integer overflow");
  }
  return left - right;
}

static final int safeMultiply(int left, int right)
                 throws ArithmeticException {
  if (right > 0 ? left > Integer.MAX_VALUE/right
                  || left < Integer.MIN_VALUE/right
                : (right < -1 ? left > Integer.MIN_VALUE/right
                                || left < Integer.MAX_VALUE/right
                              : right == -1
                                && left == Integer.MIN_VALUE) ) {
    throw new ArithmeticException("Integer overflow");
  }
  return left * right;
}

static final int safeDivide(int left, int right)
                 throws ArithmeticException {
  if ((left == Integer.MIN_VALUE) && (right == -1)) {
    throw new ArithmeticException("Integer overflow");
  }
  return left / right;
}

static final int safeNegate(int a) throws ArithmeticException {
  if (a == Integer.MIN_VALUE) {
    throw new ArithmeticException("Integer overflow");
  }
  return -a;
}
static final int safeAbs(int a) throws ArithmeticException {
  if (a == Integer.MIN_VALUE) {
    throw new ArithmeticException("Integer overflow");
  }
  return Math.abs(a);
}

2
Questo gestisce i test. Anche se non spiega come Java gestisce i underflow e gli overflow di numeri interi (aggiungi del testo per spiegare).
Spencer Wieczorek,

1

Penso che dovrebbe andare bene.

static boolean addWillOverFlow(int a, int b) {
    return (Integer.signum(a) == Integer.signum(b)) && 
            (Integer.signum(a) != Integer.signum(a+b)); 
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.