为什么在java中-(2的31次方)*(-1)还是-(2的31次方)(也就是-2147483648)?

昨天遇到1个问题,在java中对int数据取反,然后发现如果int是-(2的31次方),取反后还是它本身,然后使用 Math.abs()方法测试一下,也是一样的,查看了一下Math.abs() 就是一个简单的3目运算符

public static int abs(int a) {
    return (a < 0) ? -a : a;
}

为此去研究了一下取反的原理,以下为个人推测,目前测试结果还是正确的,有不足之处欢迎补充.

我们都知道,计算机存储的是补码(对补码不清楚的可以看我另一篇文章),根据查到的资料,取反应该是按位取反,再加1,我这边是把符号位也一起取反了,用java代码实现如下:

public int negation(int x){
    return ~x + 1;
}

然后测试了几个数据

x:-2147483648,返回:-2147483648
x:-2147483647,返回:2147483647
x:2147483647,返回:-2147483647
x:-1,返回:1
x:0,返回:0
x:1,返回:-1

和单纯的-x的效果是一样的

那么接下来我们来分析一下为什么-2147483648(也就是-(2的31次方))取反后还是它本身,int是32位,重点看头4位和尾4位

-2147483648的补码:1000 0000 0000 0000 0000 0000 0000 0000

   连符号位一起取反:0111  1111  1111  1111 1111  1111  1111  1111

                           +1:1000 0000 0000 0000 0000 0000 0000 0000

果然还是它本身

这时候会怀疑会不会是上面的分析有问题呢?

下面验证几个特殊的数据

0的补码:0000 0000 0000 0000 0000 0000 0000 0000

     取反:1111  1111  1111  1111 1111  1111  1111  1111

        +1:0000 0000 0000 0000 0000 0000 0000 0000

1的补码:0000 0000 0000 0000 0000 0000 0000 0001

     取反:1111  1111  1111  1111 1111  1111  1111  1110

        +1:1111  1111  1111  1111 1111  1111  1111  1111

-1的补码:1111  1111  1111  1111 1111  1111  1111  1111

      取反:0000 0000 0000 0000 0000 0000 0000 0000

         +1:0000 0000 0000 0000 0000 0000 0000 0001

2147483647的补码:0111  1111  1111  1111 1111  1111  1111  1111

                        取反:1000 0000 0000 0000 0000 0000 0000 0000

                            +1:1000 0000 0000 0000 0000 0000 0000 0001

-2147483647的补码:1000 0000 0000 0000 0000 0000 0000 0001

                        取反:0111  1111  1111  1111 1111  1111  1111  1110

                            +1:0111  1111  1111  1111 1111  1111  1111  1111

上面几个数都没有问题,-2147483648确实是边界问题,相信long也有一样的问题

l:-9223372036854775808,-l返回:-9223372036854775808
l:-9223372036854775808,Math.abs(l)返回:-9223372036854775808

经过验证,确实如此.

支持下载,一、数据类型 常量是有数据类型的 变量必须声明其数据类型 (1)划分: 1.基本数据类型(四类八种) 数值型: 整数型:bute、short、int、long 浮点型:float、double 字符型:char 布尔型:boolean 2.引用数据类型:除基本数据类型外的所有都是基本数据类型 数值型: 类型 所占空间 取值范围 默认值 字节型 byte 1个字节(8位) -128—127 0 短整型 short 2个字节(16位) -32768—32767 0 整形 int 4个字节(32位) +-2(的31次方)约21亿 0 长整形 long 8个字节(64位) -2(的63次方)—2(的63次方)-1 0 浮点型: 单精度浮点型 float 4个字节(32位) 1.4013E-45—3.4028E+38 0.0F 双精度浮点型 double 8个字节(64位) 4.9E-324—1.7977E+308 0.0D 字符型: 字符型 char 2个字节(16位) 0—2(的16次方)-1 \u0000 布尔型: 布尔型 boolean 1个字节(8位) ture,false false (2)整形常量常用的三种表现形式: 1.二进制 2.八进制:八进制的数以0开头 3.十六进制:十六进制的以0x开头,0ffff:一个f代表4位 二、类型的转换 1.自动转换 2.强制转换 在一个表达式,先把所有数转换成为级别最高的那个类型之后,再进行运算 byte,short,char 只要在表数范围,不用强转可以直接进行赋值。但是要是超出范围,就必须要进行强转了 类型的优先级别:byte,short,char,int,long,float,double (低–高) 右>左–强制类型转换 右<左–自动转换 右=左–不用转 三、运算符: 算术运算符: +,-,*,/,%,++,– 赋值运算符:= 关系运算符: >,<,>=,<=,==,!= instanceof 逻辑运算符: &&,||,!,^ 位运算符: &,|,^,~ , >>,<<,>>> 条件运算符:?:(三目运算符) 扩展赋值运算符:+=,-=,*=,/= 1.算数运算符(+,-,*,/,%,++,–) (1) 两个int类型数据运算,结果是int类型 两个操作数只要有一个是double类型,那么结果是double类型的数据 (2) “+”号的作用 1.表示正数 2.相加运算 3.字符串拼接 在单独运算的时候 ++i,i++ 没有任何区别,都是加1操作相当于 i=i+1 i++;先运算,后加1(先运算后加减) ++i;先加1,后运算(先加减后运算) 2.逻辑运算符(&&,||,!,^) 逻辑非 ! 取反 逻辑异或 ^ 操作数一样,结果为false;操作数不一样,结果为true 逻辑与 & 只要有一个操作数是false,那么结果就是false 短路与 && 短路与跟逻辑与 结果会一模一样。只要第一个操作数是false,那么结果一定是false,那么后面的那个操作数就不用计算了。提高了 效率。 逻辑或 | 只要有一个是true,那么结果就是true 短路或 || 短路或与逻辑或 结果一模一样。只要第一个操作数是true,那么第二个就不用计算,结果就是true。同样为了提高效率。 3.关系运算符(>,<,>=,<=,==,!=) ==:比较变量时是判断数值是否相等;比较引用变量时是判断两个在堆的存储的地址是否相等 equals:操作时是判断两个变量是否是对同一对象的引用,即对堆的内容进行比较 在比较引用变量时: ==判断的对象的地址 equals判断的是对象的内容 4.位运算符( &,|,^,~ , >>,<<,>>>) 在操作十进制数的时候首先转换为二进制的数进行操作 &:二进制都为1时为1,一个为0则为0 |:二进制都为0时为0,一个为1则为1 ^:二进制都为1时为0,一个为0则为1 ~:一个正数取~时,取反、减一、取反、加符号 一个负数取~时,直接取反
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值