java 整数相乘_Java中两个int相乘的结果是怎么算的?

与你预期结果不符的原因,其实是2147483647为int类型的最大值。

int最高只能等于这个数字,那么超过的部分的处理方式是什么呢?我用JDK11的JShell临时做了一个验证,Integer.MAX__VALUE = 2147483647;当Integer.MAX_VALUE + 1的时候,可以发现,这个时候数值是 -2147483648,即 -Integer.MAX_VALUE - 1 。

int j = Integer.MAX_VALUE + 1;

//j = -214783648, 即:- Integer.MAX_VALUE - 1.

但是,当我们继续在Integer.MAX_VALUE上面累加的时候,数值开始在负数范围内增大,变为-214783647,-214783646等。

原因是什么呢?我们知道,int占用四字节,并且最高位作为符号标志,为1的时候是负数,零的时候是正数,Integer.MAX_VALUE是当最高位为0,其他位均为1的时候,最大的在int范围内的正整数。

-214783648这个数值,就是在4字节int值全部为1的时候,由于首位表示符号,他是一个负数,由于和上一个数值相比,他的绝对值多了一。

我们不看四字节,以4位二进制举例,他和4字节二进制原理是一样的:

首先来说,这个四位二进制的最大正整数应该是多少呢:最高位为0,其余都是一,这是最大的正整数:0111 1111,记住这个数值,那么:

0111 1111 + 1

会发生什么呢:

1000 0000

变成了这样,也就是说,整体变为负数,这个数值就是负的,负数的二进制转10,需要符号位不变,其余取反并在末尾加一:

1000 0000 =取反= 0111 1111 + 1 = 1000 0000

,决对值增大了一,这就是Integer.MAX_VALUE + 1的时候的结果。那么继续累加下去呢?

1000 0000 + 1 = 1000 0001

这个数值就是负的,负数的二进制转10,需要符号位不变,其余取反并在末尾加一,即

1000 0001 =取反= 0111 1110 + 1 = 0111 1111

很明显,这个数值是原本的最大的8位整数值。但是他的绝对值和上一个数值想比减少了1,这也是Integer.MAX_VALUE + 2 后变成 Integer.MAX_VALUE本身负数的原理,以此类推,我们可以预见,继续增加数值,那么他会继续在负数的范围内增大。

语句:i *= 214783647 等价于 i = i * Integer.MAX_VALUE

即:i = Integer.MAX_VALUE * Integer.MAX_VALUE。

很明显,这个结果远超了最大值,我们能够猜测到,这四字节二进制会反复在正数和负数之间相互变化,一直到计算完成,你可以手动算下,下面是我用win10计算器得到的结果:

你可以看到,结果超过了int的范围,因此java只取了最末的4byte,即:

0000 0000 ,0000 0000 ,0000 0000, 0000 0001

因此,最终的结果变成了1.

综上所述,*=运算没有问题,它正如你期望那样的运行,只不过结果超过了int的最大值,因此你看到了1.

题主得到了问题的答案,并且进行了拓展,我在这里贴出题主的观点:我今上午也弄明白了,比如4*3,在计算的时候是

(((( [((((4+1)+1)+1)+1)] +1)+1)+1)+1)

在每一次+1时都要考虑结果溢出,如果溢出就按int最小数计算,继续+1。

昨天出这个问题是因为我直接把两数相乘,然后计算溢出的结果,而实际上应该考虑相加过程中出现的溢出情况。

同时也找到了2147483647乘以0~2147483647时,溢出后结果的规律:

2147483647*a 时,如果a是偶数,则溢出后的结果为-a;

如果a是奇数,则溢出后的结果为2147483647 - (a-1)

经四次不同数验证,结果正确。

2147483647*1时,结果为2147483647 - (1-1) = 2147483647

2147483647*2时,结果为-2

2147483647*3时,结果为2147483647 - (3-1) = 2147483645

2147483647*4时,结果为-4

2147483647*5时,结果为2147483647 - (5-1) = 2147483643

2147483647*6时,结果为-6

……

2147483647*2147483647时,结果为2147483647 - (2147483647-1) = 2147483647 - 2147483646 = 1

// 代码在这里// 如果b是偶数,溢出后的结果就等于 -b// 如果b是奇数,溢出后的结果就等于 2147483647-(b-1)public class Test{

public static void main(String[] args){

int a = 2147483647;

int b = 1;

System.out.println(a * b);

int result = simulationMultiply(a, b);

System.out.println(result);

}

public static int simulationMultiply(int num1, int num2){

int result = num1;

int count = num2;

// 这里的for 最好加上括号,以免引起误解。 for(int i = 1; i < count; i++){

for(int j = 0; j < num1; j++){

result += 1;

}

}

return result;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值