2012-09-10 7 views
5

Sto riscontrando problemi nel rilevare se una somma/moltiplicazione di due numeri supera il valore massimo di un intero lungo. Codice
Esempio:numero java supera long.max_value - come rilevare?

long a = 2 * Long.MAX_VALUE; 
System.out.println("long.max * smth > long.max... or is it? a=" + a); 

Questo mi dà -2, mentre io aspetterei a gettare un NumberFormatException ...

Esiste un modo semplice di fare questo lavoro? Perché ho un codice che fa moltiplicazioni in blocchi IF annidati o aggiunte in un ciclo e non vorrei aggiungere più IF a ogni IF o all'interno del ciclo.

Edit: Oh, bene, sembra che questa risposta da un'altra domanda è la più appropriata per quello che mi serve: https://stackoverflow.com/a/9057367/540394
Non voglio fare la boxe/unboxing in quanto aggiunge in testa unnecassary, e in questo modo è molto Insomma, questo è un grande vantaggio per me. Scriverò solo due brevi funzioni per fare questi controlli e restituire il minimo o il massimo.

Edit2: ecco la funzione per limitare una lunga al suo valore min/max in base alla risposta che ho linkato sopra:

/** 
* @param a : one of the two numbers added/multiplied 
* @param b : the other of the two numbers 
* @param c : the result of the addition/multiplication 
* @return the minimum or maximum value of a long integer if addition/multiplication of a and b is less than Long.MIN_VALUE or more than Long.MAX_VALUE 
*/ 
public static long limitLong(long a, long b, long c) 
{ 
    return (((a > 0) && (b > 0) && (c <= 0)) 
     ? Long.MAX_VALUE 
     : (((a < 0) && (b < 0) && (c >= 0)) ? Long.MIN_VALUE : c)); 
} 

Dimmi se si pensa che questo è sbagliato.

+0

+1. Ci dovrebbe essere una libreria che consente il rilevamento di overflow di interi. – Thilo

+0

O blocchi speciali (qualcosa come finalmente?) Che può aiutare gli sviluppatori a abilitare il comportamento di errore su overflow per tutto il codice matematico che viene eseguito all'interno di. Credo che C# ne abbia uno. EDIT: trovato, [blocchi selezionati e deselezionati in C#] (http://msdn.microsoft.com/en-us/library/a569z7k8.aspx). –

+0

Bene, C# sembra generare errori in overflow (che preferirei molto al silenzio e risultati errati che non hanno senso per me) ... – jurchiks

risposta

4

Se non si è certi che il risultato sarà inferiore a 9 trilioni di miliardi di dollari, vorrei utilizzare double o BigInteger Ottenere un errore non è di grande aiuto perché è ancora necessario sapere cosa fare.

Molto meglio che non si ottiene un errore in primo luogo convalidando l'input per assicurarsi che siano nel raggio d'azione e se l'intervallo del risultato è maggiore di long utilizzare un tipo che può gestire questo.

Con BigInteger si può fare

BigInteger a = BigInteger.valueOf(2).multiply(BigInteger.valueOf(Long.MAX_VALUE)); 
long l = a.longValue(); 
if (a.compareTo(BigInteger.valueOf(l)) == 0) { 
    // ok 
} else { 
    // error 
} 

con letto si può fare

double d = 2.0 * Long.MAX_VALUE; 
long l = (long) Math.max(Long.MIN_VALUE, Math.min(Long.MAX_VALUE, d)); 
// or as a helper method. 
long l = boundedCast(d); 

Nota: usando double invece di lunga può risultare in una perdita di precisione.

Preferirei evitare la necessità di un blocco di errore in primo luogo.

+1

Il fatto è che ho bisogno di ridurlo a "long" se lo supera. Forse questo aiuta? Ottenere un errore sarebbe di grande aiuto nel mio caso; Potrei semplicemente inserire l'intero codice in un blocco try/catch e se viene generato un errore, impostare il valore su Long.MAX_VALUE, perché è tutto ciò di cui ho bisogno. – jurchiks

+0

Se supera un valore lungo, non è possibile tagliarlo. Il meglio che puoi fare è renderlo 'Long.MAX_VALUE' che non è una grande soluzione. –

+3

@PeterLawrey Penso che limitarlo a 'Long.MAX_VALUE' è ciò che OP intende per * ridurlo a' long' *. – brimborium

2

Scorrendo il valore massimo di una lunga non si genera un'eccezione, invece si riavvia. Se si esegue questa operazione:

Long.MAX_VALUE + 1

si noterà che il risultato è l'equivalente di Long.MIN_VALUE.

Se si vuole lanciare un controllo un'eccezione se ha raggiunto il valore massimo e gettare l'eccezione

[Edit]

È anche possibile utilizzare il Guava Libreria per verificare se c'è un overflow quando si somma due lunghi;

long c = LongMath.checkedAdd(a, b); 

questo genera un'eccezione quando si verifica un overflow mentre sommando due long.

È possibile trovare il javadoc here

+2

"Basta fare un controllo se ha raggiunto il valore massimo" - e come lo immagina? Non voglio buttare l'eccezione da solo, non dovrei, per essere esatto. – jurchiks

+0

Puoi anche provare questo: long c = LongMath.checkedAdd (a, b); Genera un'eccezione se c'è un overflow quando si sommano 2 long –

+1

@DanielA. Forse dovresti aggiungere che hai bisogno della [libreria guava] (http://code.google.com/p/guava-libraries/) per questo. – Baz

-1

Long valori superiori MAX_VALUE non genera alcuna eccezione. È necessario controllare e gestire tali situazioni manualmente.

Anche se @PeterLawrey ha suggerito di prendere in considerazione l'utilizzo di double e BigInteger.

+0

Come si fa con un doppio? È stato pubblicato un esempio di BigInteger, ma raddoppiato ... Assegnando un doppio del valore di Long.MAX_VALUE e stampandolo, si ottiene '9.223372036854776E18'. – jurchiks

Problemi correlati