1

Javaでunsignedint変換を実行しているときに、いくつかの「異常な」結果が得られました。これは、以下に示す最小限のケースに切り詰めました。Cの同じコードは、同様の結果を生成します。

問題は、ガウス和の式n(n + 1)/ 2( https://en.wikipedia.org/wiki/Summationを参照)を使用してすべての整数値の絶対値の理論上の合計を計算すると、値Iが実際にすべての絶対値を1つずつ合計すると、calculateは合計と一致しません。

合計式を使用して合計を計算する場合、絶対値として負の数と正の数の両方を追加するため、2 "/ 2"による除算は省略され、最後に(longIntegerMax + 1)を追加する必要があることに注意してください。負の数には、最後に1つの余分な数値(Integer.MIN)があり、絶対値はInteger.MAX+1です。

public static void main( String[] asArguments ){
    long longAbsoluteTotal = 0;
    long longNumberOfIntegers = 0;
    long longIntegerMax = Integer.MAX_VALUE;
    long longIntegerMin = Integer.MIN_VALUE;
    for( int i = Integer.MIN_VALUE;; i++ ){
        longNumberOfIntegers++;
        if( i < 0 ){
            longAbsoluteTotal += i * -1;
        } else {
            longAbsoluteTotal += i;
        }
        if( i == Integer.MAX_VALUE ) break;
    }
    long longCalculatedTotal = longIntegerMax * (longIntegerMax + 1) + longIntegerMax + 1; 
    System.out.println( "count of all integers: " + longNumberOfIntegers ); 
    System.out.println( "total of absolute value of all integers: " + longAbsoluteTotal );
    System.out.println( "calculated total of absolute value of all integers: " + longCalculatedTotal );
}

出力:

 count of all integers: 4294967296
 total of absolute value of all integers: 4611686014132420608
 calculated total of absolute value of all integers: 4611686018427387904

ご覧のとおり、計算された合計は実際の合計に近いですが、正確には一致していません。なぜだめですか?

4

3 に答える 3

7

問題はここにあります..

longAbsoluteTotal += i * -1;

これ( i * -1 )は依然として整数演算であり、Integer.MAX_VALUE より大きい数値を生成し、オーバーフローして Integer.MIN_VALUE に戻ります。

@Evgeniyが提案したようにこれを修正するか、使用することができます

longAbsoluteTotal += i * -1L; 

長い演算を強制します。

于 2012-12-12T18:27:50.133 に答える
0

変化する

for( int i = Integer.MIN_VALUE;; i++ ){

for( long i = Integer.MIN_VALUE;; i++ ){

すべてがうまくいく

-Integer.MIN_VALUE == -2147483648 に似ています

于 2012-12-12T18:18:24.393 に答える
0
4611686014132420608 - 4611686018427387904 = -4294967296 = Integer.MIN_VALUE * 2

その理由は、

Integer.MIN_VALUE * -1 == Integer.MIN_VALUE

2 の補数を使用して負の値を表すためです。

Integer.MIN_VALUE(0x80000000) = 0x7fffffff + 0x1 = 0x80000000 の 2 の補数。

于 2012-12-12T18:45:31.787 に答える