Java千问:Java语言中最大的整数再加1等于多少?

已知Java语言中int类型所能表示的最大整数为2147483647,请问以下代码执行结果是什么?

一部分人都会认为这段程序压根就无法通过编译,也有人认为,这段程序能够通过编译,但在运行时会抛出异常,但更多的人面对这道题目根本就无从下手。那么正确答案是什么呢?首先告诉大家,这段程序能够顺利通过编译,并且在运行时也不会出现异常,运行的结果是在控制台上输出了数字-2147483648!而-2147483648正好是Java语言中int类型所能表示的最小整数。
这个运行结果可能会让很多人感到大跌眼镜,运行结果为什么会是这样的呢?想弄明白其中的原理,就必须先弄清楚Java语言中数字的表示和存储方式。
大家都知道:任何一个数字,存储到计算机当中,都是以二进制的形式进行存储的。在Java语言中,使用补码的形式来表示数字。那么补码是个什么东西呢?补码就是计算机用二进制的形式表示数字的一种规则。它的算法很简单:用最左边的一个二进制位表示数字的正负,0表示正数,1表示负数,我们把表示符号的这个二进制位叫做“符号位”,而剩余的二进制位表示数字本身。至于怎样用其余的二进制位表示数字,正数和负数略有区别。我们首先来说正数的情况。对于正数而言,直接用剩余二进制位表示这个数字就可以了。而对于负数而言,算法稍微复杂一点,分为两步:
一、用补码表示出这个数的绝对值,之后把每个位上的数字(连同符号位上的数字在内)按位取反,所谓按位取反就是如果这个位上原来是0,那么就变成1,如果原来这个位上原来是1,那么就变成0。
二、就是把这个取反以后的数字加上1,就得到了负数的补码表示结果。
没看懂?没关系!咱们用例子说事。首先必须知道,Java语言中int类型的数据占4个字节,那么4个字节所能表示的最大整数是多少呢?按照补码的表示规则,这个最大的整数存储到计算机当中应该是“1个0跟31个1”:

如果我们强行给这个数再加1,按照二进制的进位规则,它会变成下面的样子:

这个数是多少?会是0吗?我们来分析一下:首先最左边的符号位从0变成了1,所以可以肯定,这个数是个负数。那么一个正数做了加1的操作,它应该变成一个更大的正数,现在怎么变成负数了呢?我们必须清楚,原来这个数的符号位是0,是因为加法运算产生了“进位”,才使得符号位变成了1,但是,计算机不管那么多,它只要看到最左边的符号位是1,就认定这是一个负数。那么,这个负数的值是多少?我们可以按照补码表示负数的规则,以逆运算的方式求出它的绝对值,就知道这个负数的值了。
前面讲过:用补码表示负数的算法分两步进行,其中第二步,是在二进制数字上加1。那么反过来,这个过程的逆运算也要分两步进行。其中第一步就应该是在原负数补码的数字上减1,减1之后,刚才的数字就会变成下面的样子

补码求负数的第一步是对二进制数字按位取反,所以逆运算的第二步也是对各个位上的数字(连同符号位上的数字在内)按位取反,使得各个位数字恢复到原来的值。经过按位取反之后,刚才那个二进制数字又会变成下面的样子

细心的读者可能已经发现,折腾了半天,又回到了逆运算之前的样子!大家注意:表面上,这个二进制数跟逆运算之前是一个样,但是它的意义已经完全不同了。在进行逆运算之前,这个二进制数是一个补码形式表示的负数,而经过逆运算之后,这个二进制数变成了一个绝对值,既然是绝对值,它肯定不会是负数。因此,这个二进制数最前面的1并不表示负数,而是数字的一部分。那么这个绝对值是多少呢?转换成十进制就是2147483648。所以,我们图3中看到的那个“1开头后面跟着31个0”所表示的负数,就是-2147483648!
到此为止,我想大家已经明白为什么程序的运行结果是-2147483648了吧?可能有一部分读者会问:补码当中,“1开头后面跟着31个0”这个数字为什么不能解释为:符号位上的1表示负数,后面的31位数字表示0,这样形成的数字是-0,也就是0呢?其实,补码的运算规则中特意强调了这一点。规则强调:补码当中,对于0只有唯一一种表示形式,那就是32个0,其中最前面的0表示符号,后面的0表示数字。一旦遇到符号位是1,后面全是0的情况,必须按负数对待!既然要求我们按负数对待,那就必须通过逆运算来计算这个负数的绝对值。而我们计算得到的这个负数的绝对值就是2147483648。-2147483648是int类型的所能表示的最小值。因此,int类型数据的最大值再加1,一下子就变成了int类型的最小值,我们可以戏称为“物极必反现象”。
那么,Java语言当中,其他三种类型的整数是否也有“物极必反现象”呢?对于long类型的变量来讲,也存在这种现象,而对于byte和short类型,我们使用其最大值和1进行加法运算,无法再赋值给byte和short型的变量,因为这种操作在编译时就会报错。关于byte和short变量无法完成这种赋值操作的原因,大家可以看我的另一篇博文《Java千问:Java语言中为byte和short类型变量赋值为啥会报错?》进行详细了解。
另外,通过这个例子,大家也应该明白为什么Java语言中,整数类型的表示范围是不对称的。比如, byte类型的数据最大值是是127,而最小并不是-127,而是-128。其原因就是补码规则中,把0当作了正数看待,这样的话正数这边有个0,而负数那边没有,从而表示范围不对称。

原文地址:https://blog.51cto.com/2266836/2462128

时间: 2025-01-18 07:33:43

Java千问:Java语言中最大的整数再加1等于多少?的相关文章

Java千问:关于Java语言复合赋值运算符的两个问题,快来瞧瞧!

我们知道,在Java以及很多高级编程语言当中,都有一种运算符叫做复合赋值运算符.复合赋值运算符由两个符号组成,它所能完成的运算操作也分为两步:第一步是运算,第二步是赋值.比如说:上面的这两条语句相当于但是,如果碰到下面这样的情况,a的值该应该是多少呢?有人认为应该按以下方式来计算,因为我们都知道,在四则运算规则中,遵循"先乘除,后加减"的原则按照这样的方式来计算,得到a的值应该是7,但实际运行程序所得到的结果是8.这是为什么呢?就是因为复合赋值运算符在完成运算的时候,遵循一个规则:把&

Java千问:Java位运算经典应用(一)

很多人认为位运算在实际开发过程中并没什么用,学习位运算也只是为了应付面试.这种想法是错误的,接下来我们就通过几篇连载文章介绍一下位运算在实际开发过程中的几个经典应用实例.如果对位运算规则掌握还不是很熟练,可以先阅读<Java千问:Java语言位运算符详解>.这篇文章不仅详细讲解了Java位运算的基本规则和一些常用的运算定律,同时还在文中提到了一些常用的位运算实际应用,比如可以用位运算操作的方式快速把某个变量所在的内存单元清零,或者位运算的方式实现某个变量快速倍增等等.但文中所这提到的这几个实际

Java千问:Java位运算经典应用(二)

接上篇 三.不借助中间变量交换两个变量的值 通常情况下,我们要交换两个变量的值都按如下步骤操作: 这种操作方式不难理解,实现交换变量值的关键点就在于中间变量c.而现在的题目要求是不借助中间变量来交换a和b的值.如果不使用位运算的方式,同样可以做到不借助中间变量交换两个变量的值,其实现过程如下. 为了讲解方便,我们把最初a与b的值称之为原始a和原始b,3行代码就是3步操作:第1步:把原始a与原始b相加的和存储到变量a中,变量b的值暂时没有发生变化.第2步:用这个和减去原始b,再赋值到变量b中,经过

《Java千问》系列短文写作计划

大家好,我在51CTO开博客啦!我本人从事软件开发和教学多年,在我从事教学过程中,回答过很多学生的问题,但非常遗憾,我只是当场回答了这些问题,但事后并没有把这些问题的解答写成博客.我打算弥补一下这个缺憾,因此产生了写文章解答问题的想法.经过几天酝酿,我打算把这些文章写成系列短文,名字就叫<Java千问系列>.取这个名字并不是说真的有一千个问题,"千"只是表示多的意思.只要我有把握回答的,都发表出来.关于<Java千问系列>的文章,在这里我想做几点说明:一.<

python基础知识 05 python语言中的大整数

第五课 python语言中的大整数 java中的int 最大可以处理 2^31 -1(2147483647) 最小呢-2^31 (-2147483647)但是在Java中可以使用BigInteger 来处理无线大的数 print(2 ** 60) 结果为 1152921504606846976 print(2 ** 600) 41495155688809929585124078636911611510124462322424368999956573296906528114129081463997

Java千问:Java语言各种数字的“非常规”写法你都会吗?

Java程序中总是会出现一些数字.我们通常都是用常规的方式来表示这些数字,如以下代码所示 int a = 1; double b = 1.5; 但是数字也可以有非常规写法,在这里我们用一篇短文简单总结一下 整数的非十进制写法首先强调一下,这里所说的整数并不是单指int类型,而是包含了int.byte.short和long这4种整数类型.在Java语言中,除了可以用十进制的形式表示整数以外,还可以用二进制.八进制和十六进制的方式表示整数.如果用十六进制的形式表示一个整数,数字要以0X开头,如果用八

Java千问:Java语言中为byte和short类型变量赋值为啥会报错?

咱们先来看一段很简单的Java代码这段代码非常简单,没有任何技术含量.但是,如果我们把这段代码改成下面的样子大家可以看到,我们只是用一个变量a代替了原来赋值表达式当中的常量1,就会出现语法错误,这是为什么呢?今天我们就用一篇短文来聊聊这个话题.我们知道,Java语言中有4种整数类型,分别是byte.short.int和long.其中,Java编译器对byte和short类型的变量在赋值的时候,做了一点点"特殊检查".那么编译器如何"特殊检查"这两种类型的变量呢?当编

Java千问:七个问题帮助初学者深入理解Java数组

几乎所有的高级语言当中,都提供了一种叫做"数组"的东西,Java语言当然也不例外.我们通过数组可以很方便的存储和管理一组数据.因为在Java语言当中使用数组非常的方便,所以导致很多初学者忽略了对数组的深入学习,本文就通过七个问题,来帮助初学者深入理解一下Java语言的数组到底是怎么回事. 一.数组是变量的简单叠加吗? 我们在学习Java的时候,知道一个int类型的变量可以存储一个整数,而一个int类想的数组可以存储多个整数.于是很多人认为数组只不过是变量的简单叠加而已,无非是变量存1个

Java千问:开发Java程序为什么要配置环境变量?

我们在学习搭建Java开发环境的时候,老师总是让我们先安装JDK,紧接着又让我们去配置环境变量,之后才能动手编写Java程序.很多同学按照老师的步骤去做,成功的搭建好了Java开发环境,并且运行出了自己的第一个Java程序,感到非常有成就感. 那么,为什么在安装了JDK之后要配置环境变量呢?很多同学对这个问题其实并不清楚,只是知道如果不配置环境变量,就没法进行Java开发.今天,咱们就来聊聊为什么要配置环境变量.其实,配置环境变量的目的很简单:为了在命令行窗口下编译和运行Java程序.大家请注意