在Java中进行无符号int转换时,我得到了一些“异常”结果,我已将其减少到下面显示的最小情况。 C中的相同代码会产生类似的结果。
问题在于,当我使用高斯求和公式n(n + 1)/ 2(参见https://en.wikipedia.org/wiki/Summation)计算所有整数值的绝对值的理论总和时,我计算的值与总和,如果我实际上逐个加起所有绝对值。
请注意,当我使用求和公式计算总数时,省略除以2“/ 2”,因为我将正数和正数都加为绝对值,最后我必须添加(longIntegerMax + 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
如您所见,计算出的总数接近实际总数,但与其完全不符。为什么不呢?
答案 0 :(得分:7)
问题出在这里..
longAbsoluteTotal += i * -1;
( i * -1 )
仍然是整数运算,它产生的数字大于Integer.MAX_VALUE并溢出回Integer.MIN_VALUE;
你可以修改这个@Evgeniy建议,或者你可以使用
longAbsoluteTotal += i * -1L;
强制进行长算术。
答案 1 :(得分:0)
更改
for( int i = Integer.MIN_VALUE;; i++ ){
到
for( long i = Integer.MIN_VALUE;; i++ ){
一切都会好的
类似于-Integer.MIN_VALUE == -2147483648
答案 2 :(得分:0)
4611686014132420608 - 4611686018427387904 = -4294967296 = Integer.MIN_VALUE * 2
原因是
Integer.MIN_VALUE * -1 == Integer.MIN_VALUE
因为我们使用二进制补码来表示负值。
Integer.MIN_VALUE(0x80000000)= 0x7fffffff + 0x1 = 0x80000000的两个补码。