クイックアプローチ
これは解決策になる可能性があります (注:常に意味のある変数名を使用してください!):
private static int sum(int i, int... others) {
int sum = i;
if(others!=null)
for(int other : others) {
sum+=other;
}
}
System.out.println("sum:" + sum);
return sum;
}
引数に注意してください。1 つの数値を合計することはあまり意味がないため、この構成により、少なくとも 1 つの int が入ってくることが保証されます。また、これは vararg の null 値もチェックします。
溢れる感情…
これを実行すると、クイックアプローチで何が起こるでしょうか:
int veryBigNumber = sum(Integer.MAX_VALUE, 1);
veryBigNumber
実際には==Integer.MIN_VALUE
...
これは問題になる可能性があります。オーバーフローが発生しても Java は例外をスローしないため、誤った結果になる可能性があります。オーバーフローのチェックを行うことができます:
private static int aLittleBitSaferSum(int i, int... others) throws ArithmeticException {
int sum = i;
if(others!=null)
for(int other : others) {
if(Integer.MAX_VALUE-other<sum) {
throw new ArithmeticException("Sum would be too large to fit in int");
}
if(Integer.MIN_VALUE+other>sum) {
throw new ArithmeticException("Sum would be too small to fit in int");
}
sum+=other;
}
}
System.out.println("sum: " + sum);
return sum;
}
もちろん、これはただのばかげたチェックです...結果はint
、たとえば次のように に非常にうまく収まる可能性があります。
sum(Integer.MAX_VALUE, 1, -1);
どちらが結果になるはずですかInteger.MAX_VALUE
-チェックなしです。
視野を広げる
恐れるな!前述の問題も解決できます。たとえば、部分的な結果が常にint
範囲内に収まるようにオペランドを順序付けする巧妙なアルゴリズムを提供することによって、それは解決するのが簡単ではない問題だと思います...そして計算能力に多くの費用がかかります.
ただし、関数が処理する値の範囲を拡張することで、はるかに優れた処理を実行できます。
private static int aLittleBitSaferSum(int i, int... others) throws ArithmeticException {
long sum = i;
if(others!=null)
for(int other : others) {
if(Long.MAX_VALUE-other<sum) {
throw new ArithmeticException("Sum would be too large for this algorithm to deal with");
}
if(Long.MIN_VALUE+other>sum) {
throw new ArithmeticException("Sum would be too small for this algorithm to deal with");
}
sum+=other;
}
}
if(Integer.MAX_VALUE<sum) {
throw new ArithmeticException("Sum would be too large to fit in int");
}
if(Integer.MIN_VALUE>sum) {
throw new ArithmeticException("Sum would be too small to fit in int");
}
System.out.println("sum: " + sum);
return (int)sum;
}
これにはまだ制限がlong
ありますlong
が、整数の 2 倍のサイズであるため、問題が発生する可能性ははるかに低くなります。ただし、これは余分な作業が必要なため少し遅くなり、チェックのために読みにくくなります。
全部欲しい
…今すぐ欲しい。範囲はまだ問題になる可能性がありますが、これは解決策です:
private static int aSafeButSlowerSum(int i, int... others) throws ArithmeticException {
BigInteger sum = BigInteger.valueOf(i);
BigInteger intMax = BigInteger.valueOf(Integer.MAX_VALUE); //should be a private static final class variable
BigInteger intMin = BigInteger.valueOf(Integer.MIN_VALUE); //should be a private static final class variable
if(others!=null)
for(int other : others) {
sum=sum.add(BigInteger.valueOf(i));
}
}
if(intMax.compareTo(sum)<0) {
throw new ArithmeticException("Sum would be too large to fit in int");
}
if(intMin.compareTo(sum)>0) {
throw new ArithmeticException("Sum would be too small to fit in int");
}
System.out.println("sum: " + sum.toString());
return sum.intValue;
}
これはすべての BigInteger が原因でさらに遅くなりますが、上記の関数の問題は見られません。(したがって、他のオプションと同様に「現在」は少し少なくなりますが、追加料金を支払う必要があります..)