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;
}
}
java 整数相乘_Java中两个int相乘的结果是怎么算的?相关推荐
- java long 区别_java中long和int的区别
java中long和int的区别 发布时间:2020-06-26 15:37:48 来源:亿速云 阅读:191 作者:Leah 这篇文章将为大家详细讲解有关java中long和int的区别,文章内容质 ...
- java合并整形_java中2个int合并成一个long
延续32位时代的逻辑通常只会在32位整数中取出高16位和低16位的短整数(short)或相反的合并操作,如c/c++语系中loword和hiword.现在64位的cpu普及到已是标配了,所以这种经典的 ...
- java ftp 教程_Java 中两种ftp操作方式
最近看到几篇关于java中操作ftp的文章,所以想写一个总结贴,标记一下,方便以后应用. 首先,我们可以应用java中的ftp库,java中提供了一个ftpclient的类,提供了很多操作ftp的方法 ...
- java+map申明_Java中两种HashMap申明方式区别?
Map是HashMap的父类,第一种声明方式是:父类的引用指向子类的对象,是多态的一种表现形式:第二种是:使用本身引用.举个例子: 第一种声明方式是实现了多态,多态后就可以写出一段所有子类都通用的代码 ...
- Java黑皮书课后题第8章:**8.6(代数:两个矩阵相乘)编写两个矩阵相乘的方法。编写一个测试程序,提示用户输入两个3*3的矩阵,然后显示它们的乘积
**8.6(代数:两个矩阵相乘)编写两个矩阵相乘的方法.编写一个测试程序,提示用户输入两个3*3的矩阵,然后显示它们的乘积 题目 题目描述与运行示例 破题 代码 题目 题目描述与运行示例 **8.6( ...
- 线性代数中两个向量相乘_加两个向量| Python的线性代数
线性代数中两个向量相乘 Prerequisite: Linear Algebra | Defining a Vector 先决条件: 线性代数| 定义向量 In the python code, we ...
- java 定义整数数组_JAVA中数组的正确定义方法是什么?
数组是有序数据的集合,数组中的每个元素具有相同的数组名和下标来唯一地确定数组中的元素. §5.1一维数组 一.一维数组的定义 type arrayName[]; 其中类型(type)可以为Java中任 ...
- java两个矩阵相乘_java计算两个n阶矩阵相乘
自己是个新手,研究java数据结构,看到两个n阶矩阵相乘的题目,自己就试着写了一个简单的demo,哪里有不好的地方,也希望大家多提提意见,直接上代码了: package com.shujujiegou ...
- java string转int 异常_Java中String转int型的方法以及错误处理
应要求,本周制作了一个判断一个年份是否是闰年的程序.逻辑很简单,这里就不贴代码了.可是,在这次程序编写中发现了一个问题. 在输入年份时,如果输入1)字母2)空3)超过Int上限时,就会抛excepti ...
- Java中用三种方法输出字符串_java中两个字符串连接的三种方法
java中两个字符串连接有以下三种方法: 第一种方法:使用+: 第二种方法:使用concat(): 第三种方法:使用append(): 如下代码: public class Practice { // ...
最新文章
- findbugs:may expose internal representation by ret
- 年薪80万技术专家,面试通过后,被发现简历造假!合并8年前多段工作!惨遭警告和淘汰!...
- 2021机器智能研究方向
- python 400集大型视频下载_Python400集大型视频,无偿分享,从正确方向学习python...
- 凑个热闹-LayoutInflater相关分析
- 六条“黑客伦理”(hacker ethic)
- MicroPython支持SPI驱动外部Flash了
- 基于springboot的在线考试系统
- 小程序流量主运营技巧
- Ae:时间轴面板(图层控制区)
- 罗马数字转换器|罗马数字生成器
- cdh 6.x、cdh 5.16.x、cdh 5.15.x、cdh 5.14.x、cdh 5.12.x组件对应版本
- 031_组件 reRender控件和rendered控件的使用
- simulink模块名称显示设置_GUI界面实现批量修改Simulink模块参数名称
- 世界各地的标志性建筑物
- 小心肝队-冲刺日志(第五天)
- 2020最新的web前端体系和路线图,想学web前端又不知道从哪开始的快来瞧一瞧呀
- 一款新型的maphack
- 软件技术专业就业方向分析
- ROS(ERROR):Rosdep cannot find all required resources to answer your query
热门文章
- RHCE认证培训+考试七天实录(七)
- 在主函数中输入10个等长的字符串。用另一函数对他们排序
- Some tips from Inject Lib sample application
- 乘风破浪:LeetCode真题_019_Remove Nth Node From End of List
- Web Service(二):cxf 实现
- Delphi动态调用C++写的DLL
- phpstudy连接SQL Server 2008数据库 以及 php使用sql server出现乱码解决方式
- 提高性能及操作硬件的能力
- PPT设计的数据图表化表现
- DIV 内滚动条 样式的写法