2012-09-10 13 views
5

Ich habe Probleme festzustellen, wenn eine Summe/Multiplikation von zwei Zahlen den Maximalwert einer langen Ganzzahl überschreitet.
Beispielcode:Java-Nummer überschreitet long.max_value - wie zu erkennen?

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

Das ist mir -2 gibt, während ich es ein NumberFormatException ...

Gibt es eine einfache Art und Weise zu machen, diese Arbeit zu werfen erwarten würde? Weil ich Code habe, der Multiplikationen in verschachtelten IF-Blöcken oder Additionen in einer Schleife ausführt, und ich würde es hassen, jeder IF oder innerhalb der Schleife mehr IFs hinzuzufügen.

Edit: na ja, so scheint es, dass diese Antwort von einer anderen Frage ist die am besten geeignete für das, was ich brauche: https://stackoverflow.com/a/9057367/540394
Ich will nicht Boxen/Unboxing tun, wie es unnecassary Overhead hinzufügt, und auf diese Weise ist sehr kurz, das ist ein großes Plus für mich. Ich werde nur zwei kurze Funktionen schreiben, um diese Überprüfungen durchzuführen und die Min- oder Max-Länge zurückzugeben.

Edit2: hier ist die Funktion für eine lange seine Min-/Max-Grenzwert nach der Antwort, die ich oben verlinkten:

/** 
* @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)); 
} 

Sag mir, wenn Sie denken, das ist falsch.

+0

+1. Es sollte eine Bibliothek geben, die Integer-Überlauferkennung ermöglicht. – Thilo

+0

Oder spezielle Blöcke (etwas wie endlich?), Die Entwickler helfen können, Fehler-auf-Überlauf-Verhalten für alle Math-Code, der innerhalb ausgeführt wird. Ich glaube, C# hat eine. Bearbeiten: Es gefunden, [aktiviert und deaktiviert in C#] (http://msdn.microsoft.com/en-us/library/a569z7k8.aspx). –

+0

Nun, C# scheint Fehler auf Überlauf zu werfen (was ich sehr über Schweigen und falsche Ergebnisse, die für mich keinen Sinn machen würde) ... – jurchiks

Antwort

4

Wenn Sie nicht sicher sein können, das Ergebnis wird weniger als 9 Billionen Billionen sein, würde ich verwenden double oder BigInteger Einen Fehler zu bekommen hilft Ihnen nicht sehr, weil Sie noch wissen müssen, was zu tun ist.

Viel besser, dass Sie überhaupt keinen Fehler erhalten, indem Sie Ihre Eingabe validieren, um sicherzustellen, dass sie sich in Reichweite befinden und wenn der Bereich des Ergebnisses größer als long ist, verwenden Sie einen Typ, der das verarbeiten kann.

Mit BigInteger können Sie

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 
} 

zu tun mit Doppel Sie

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); 

Hinweis tun können: mit double statt in einem gewissen Verlust an Präzision führen kann lange.

Ich würde lieber die Notwendigkeit für einen Fehlerblock in erster Linie vermeiden.

+1

Die Sache ist, ich muss es auf 'lang' abschneiden, wenn es es übersteigt. Vielleicht hilft das? Einen Fehler zu bekommen würde in meinem Fall viel helfen; Ich könnte einfach den ganzen Code in einen try/catch-Block setzen und wenn ein Fehler ausgelöst wird, setze den Wert auf Long.MAX_VALUE, denn das ist alles was ich brauche. – jurchiks

+0

Wenn es eine lange überschreitet, können Sie es nicht schneiden. Das Beste, was Sie tun können, ist 'Long.MAX_VALUE', was keine großartige Lösung ist. –

+3

@PeterLawrey Ich denke, es ist auf 'Long.MAX_VALUE' zu beschränken, was OP damit meint * trimme es runter auf' long' *. – brimborium

2

Das Überschreiten des Maximalwerts einer langen Ausgabe führt nicht zu einer Ausnahme, sondern zur Rückgabe. Wenn Sie dies tun:

Long.MAX_VALUE + 1

Sie werden feststellen, dass das Ergebnis das Äquivalent zu Long.MIN_VALUE ist.

Wenn Sie es wünschen, eine Ausnahme Prüfung zu werfen, wenn er den Maximalwert erreicht und werfen die Ausnahme

[Bearbeiten]

Sie können auch die Guava Bibliothek verwenden zu überprüfen, ob ein Überlauf ist, wenn Sie Summe zwei Longs;

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

Dies löst eine Ausnahme aus, wenn während der Summierung von zwei Longs ein Überlauf auftritt.

Sie finden das javadoc here

+2

"einfach tun, wenn überprüft, ob es den maximalen Wert erreicht" - und wie stellst du dir das vor? Ich will die Ausnahme nicht selbst werfen, ich sollte nicht, um genau zu sein. – jurchiks

+0

Sie können dies auch versuchen: long c = LongMath.checkedAdd (a, b); Wenn bei der Summierung von 2 Longs –

+1

@DanielA ein Überlauf auftritt, wird eine Ausnahme ausgelöst. Vielleicht sollten Sie hinzufügen, dass Sie dafür die [Guava-Bibliothek] (http://code.google.com/p/guava-libraries/) benötigen. – Baz

-1

Long Werte MAX_VALUE überschreitet werfen keine Ausnahme. Sie müssen solche Situationen manuell überprüfen und behandeln.

Obwohl @PeterLawrey vorgeschlagen hat, sollten Sie die Verwendung von double und BigInteger in Betracht ziehen.

+0

Wie machst du das mit einem Doppel? Ein BigInteger-Beispiel wurde gepostet, aber doppelt ... Wenn ich einen doppelten Wert von Long.MAX_VALUE gebe und ihn drucke, bekomme ich '9.223372036854776E18'. – jurchiks

Verwandte Themen