2012-01-29 6 views
9

よりも大きなa + bLong.MAX_VALUE/Long.MIN_VALUEより小さく/大きくなっていないことを確認する簡単な方法はありますか? Guavaを使用してロング+ロングはLong.MAX_VALUE

+0

はどのようにするために、質問テキストボックスの右に、そしてそれ以上** **リンク(およびその下のプレビュー)に**ボックスをフォーマットするために**方法を参考にしてください質問を適切に書式設定する –

+0

アセンブラでは、*キャリー*フラグをチェックできますか? –

+0

私は[宿題]タグを削除しました。コメントスレッドで言及されているOPは偶然にしか存在しなかったためです。 –

答えて

17

は、それは同様に簡単です

long c = LongMath.checkedAdd(a, b); // throws an ArithmeticException on overflow 

として、私は確かに、非常に読みやすいと思いますしたいと思います。 (LongMath Javadoc here

公平のために、私はApache CommonsがArithmeticUtils.addAndCheck(long, long)を提供していると言います。

どのように動作するのかを知りたい場合、答えはグアバのビットハッピーの1行です。(a^b) < 0 | (a^(a + b)) >= 0の場合、結果はオーバーフローしません。これは、同じ符号を持つ場合、2つの数値のビットごとのXORが負ではないというトリックに基づいています。

abの符号が異なる場合は、(a^b) < 0は真ですが、その場合はオーバーフローしません。または、(a^(a + b)) >= 0の場合、a + baと同じ符号を持つため、オーバーフローせずにマイナスになります。

(このようなより多くのトリックのために、素敵なブックHacker's Delightを調査する。)

Apacheはabの符号に基づいて、より複雑なケースワークを使用しています。

+0

グアバの+1。 (私が最初に示唆したように)比較しても(私はそれが適切だと思うには眠すぎるが)、すぐに使える機能を好む。 – Bozho

+0

全開示:私は 'LongMath'の著者で、残りはGuavaのcommon.mathパッケージの...しかし、@Bozhoは、独自の実装をロールバックするのではなく、一般的にライブラリコードに頼っている方が一般的には良いということは間違いありません。(特に、このコードはすでに非常に徹底的にテストされているので、必要ありません!) –

+0

非常にクールです。このような単純なケースでは、別のライブラリ全体を追加するのは難しいかもしれません(この場合、オーバーフローを検出するのは簡単です)。しかし、既にGuavaを使用している場合は... –

0

1つのオプションは、正確な計算を行うためにBigIntegerクラスを使用し、その結果が問題の値よりも大きいか小さいかをチェックすることです。例:

if (BigInteger.valueOf(a).add(BigInteger.valueOf(b)).compareTo(BigInteger.valueOf(Long.MAX_VALUE) > 1) { 
    /* Overflow occurred. */ 
} else { 
    /* No overflow occurred. 
} 

これが役に立ちます。

+0

フルパワーを使うなら'BigInteger'の' myBigInt.bitLength()

+0

@LouisWassermanは、より小さいために正しい、そうでなければ、1だけ離れているでしょう。私は2つのオプションのいずれかが読めるとは思わないし、答えの1つはLong.MIN_VALUEではなくLong.MAX_VALUEでしかないと思う。 –

+0

これはこれよりも読みにくいということに同意した。参考のため、BigIntegerアプローチは、ライブラリを使用したくない場合は、*乗算*のオーバーフローをチェックする最も読みやすい方法です。 –

0

簡単なルート:

if(a/2+b/2+(a&b&1)>long.MAX_VALUE/2||a/2+b/2<long.MIN_VALUE/2)... 

あなたはちょうど彼らが同じ符号を持つ(両方!0ある)場合にのみ問題だ、それは(a+b)/2

+0

私はこれが正しく動作するとは思わない。 a = Long.MAX_VALUEとb = 1を取ると、2つの値を加算するとオーバーフローがはっきりしますが、a/2 = Long.MAX_VALUE/2とb/2 = 0になるので、a/2 + b/2 <= Long.MAX_VALUE。 – templatetypedef

+0

@templatetypedef私はそれを解決しました(オーバーフローを追加しました) –

13

に最適化されないことを願ってする必要があり、それ以外の場合は、オーバーフローから安全です。オーバーフローが発生した場合、結果の符号が反転します。だから、:[?]

long r = a + b; 
if ((a < 0 && b < 0 && r >= 0) || 
    (a > 0 && b > 0 && r <= 0)) { 
    // Overflow occurred 
} 
+2

投票した、最も簡単で、最も読みやすく、最良の方法。うまくいけば、このコースはもっと最適化された数学的方法には向かないでしょう。 –

+0

@ owlsteadコンパイラが十分にスマートな場合は、CPUの "キャリー"フラグを使うことができるので、解決策は十分です。唯一の算術演算がキャリーを介して行われた日に戻ってください。 – bestsss

+1

ほとんどの宿題に適した解決策がアップされました。 –

関連する問題