2012-09-10 6 views
5

2つの数値の合計/乗算が長い整数の最大値を超えているかどうかを検出する際に問題があります。
例コード:Java番号がlong.max_valueを超えています - どのように検出するのですか?

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

私はそれがNumberFormatException ...

を投げることを期待しながら、これは、私に-2を与え、この作品を作る簡単な方法はありますか?ネストされたIFブロックまたはループ内での加算で乗算を行うコードがいくつかあるので、各IFまたはループ内にIFを追加することは嫌です。

編集:まあ、別の質問から、この答えは私が必要なもののために最も適切であると思わ:https://stackoverflow.com/a/9057367/540394
私はそれがunnecassaryオーバーヘッドが追加されますようにボクシング/アンボクシングを行うにはしたくないし、この方法は非常にあります短く、私には大きなプラスです。私はちょうど2つの短い関数を書いて、これらのチェックを行い、最小値または最大値を返します。

EDIT2:あなたは、これは間違っていると思われる場合

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

を教えてください:ここで私は上記にリンクされて答えに応じてその最小/最大値に長いを制限するための機能です。

+0

+1。整数オーバーフローの検出を可能にするライブラリが必要です。 – Thilo

+0

また、開発者がin-inで実行されるすべての数学コードのオーバーフローエラーを可能にする特別なブロック(最終的に何か?)があります。編集:それは[C#のブロックをチェックし、チェックを外した](http://msdn.microsoft.com/en-us/library/a569z7k8.aspx)を見つけました。 –

+0

まあ、C#はオーバーフロー(私は非常に沈黙と私に意味をなさない間違った結果を好むだろう)のエラーをスローするようだ... – jurchiks

答えて

4

結果が9兆兆未満であるかどうかわからない場合は、doubleまたはBigIntegerを使用します。エラーが発生しても、何をすべきかを知る必要があります。

入力を検証して範囲内にあることを確認し、結果の範囲がlongより大きい場合は、これを処理できるタイプを使用するとエラーが発生しない方がずっと優れています。代わりに長いのdoubleは、精度のいくつかの損失につながることができます使用する:

のBigIntegerで

あなたは

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

注を行うことができます倍増して

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 
} 

を行うことができます。

まず、エラーブロックの必要性を避けることをお勧めします。

+1

それはそれを超えると「ロング」にトリムする必要があります。多分それが助けますか?私の場合、エラーを得ることは大いに役立ちます。私はtry/catchブロックにコード全体を置くことができ、エラーがスローされた場合、値をLong.MAX_VALUEに設定します。 – jurchiks

+0

長すぎる場合は、トリムできません。あなたができることは、 'Long.MAX_VALUE'にすることです。これは素晴らしい解決策ではありません。 –

+3

@PeterLawrey私は 'Long.MAX_VALUE'にキャップすると、OPが意味するものであると考えられます。*これを' long' *にトリミングします。 – brimborium

2

longの最大値を超えると、例外がスローされます。あなたがこれを行う場合:

はLong.MAX_VALUE + 1

あなたは結果はLong.MIN_VALUEと同等であることがわかります。

あなたはそれが最大値に達した場合は、例外チェックをスローし、例外

をスローするようにしたい場合は、[編集]

ます。またときにオーバーフローがあるかどうかを確認するためにGuavaライブラリを使用することができます2つの長さを合計する。

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

2つのlongを合計している間にオーバーフローが発生すると例外がスローされます。

あなたはjavadocのに任意の例外をスローしませんMAX_VALUEを超えるhere

+2

"最大値に達したかどうかを確認するだけです" - どのように想像していますか?私は例外を自分自身に投げたくはありません、私は正確であるべきではありません。 – jurchiks

+0

これを試すこともできます:long c = LongMath.checkedAdd(a、b); @DanielAの2つの長さを合計するとオーバーフローが発生すると、例外がスローされます。 –

+1

たぶんあなたはこれを追加する必要があります、[Guavaライブラリ](http://code.google.com/p/guava-libraries/)が必要です。 – Baz

-1

Long値を見つけることができます。このような状況を手動で確認して処理する必要があります。

@PeterLawreyとして、doubleBigIntegerを使用することをお勧めします。

+0

どのようにダブルでこれを行うのですか? BigIntegerの例が掲載されていますが、double ... Long.MAX_VALUEの値を2倍にして印刷すると、 '9.223372036854776E18'となります。 – jurchiks

関連する問題